//
// (C) Copyright 2009 Irantha Suwandarathna (irantha@gmail.com)
// All rights reserved.
//

/* Copyright (c) 2001-2008, The HSQL Development Group
 * All rights reserved.
 *
 * Redistribution and use _in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * Redistributions of source code must retain the above copyright notice, this
 * list of conditions and the following disclaimer.
 *
 * Redistributions _in binary form must reproduce the above copyright notice,
 * this list of conditions and the following disclaimer _in the documentation
 * and/or other materials provided with the distribution.
 *
 * Neither the name of the HSQL Development Group nor the names of its
 * contributors may be used to endorse or promote products derived from this
 * software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL HSQL DEVELOPMENT GROUP, HSQLDB.ORG,
 * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */


using System;
using System.Text;
using System.Collections.Generic;
using System.Reflection;
using System.Linq;
using System.Resources;
using System.IO;
using EffiProz.Core.DataTypes;
using EffiProz.Core.Lib;
using EffiProz.Core.Persist;
using EffiProz.Core.ScriptIO;
using EffiProz.Core.Rights;
using EffiProz.Core.Results;


namespace EffiProz.Core.DbInfos
{


    // fredt@users - 1.7.2 - structural modifications to allow inheritance
    // boucherb@users - 1.7.2 - 20020225
    // - factored _out all reusable code into DIXXX support classes
    // - completed Fred's work on allowing inheritance
    // boucherb@users - 1.7.2 - 20020304 - bug fixes, refinements, better java docs
    // fredt@users - 1.8.0 - updated to report latest enhancements and changes
    // boucherb@users - 1.8.0 - 20050515 - furhter SQL 2003 metadata support

    /**
     *:DatabaseInformationMain to provide additional system table
     * support. <p>
     *
     * @author boucherb@users
     * @version 1.8.0
     * @since 1.7.2
     */
    class DatabaseInformationFull : DatabaseInformationMain
    {

        static HashMappedList statementMap;

        static DatabaseInformationFull()
        {
            String resourceFileName =
                "EffiProz.Core.Resources.information-schema.sql";
            String[] starters = new String[] { "/*" };
            Stream fis = Assembly.GetExecutingAssembly().GetManifestResourceStream(resourceFileName);

            StreamReader reader = null;

            try
            {
                reader = new StreamReader(fis, Encoding.UTF8);
            }
            catch (Exception ) { }

            LineGroupReader lg = new LineGroupReader(reader, starters);

            statementMap = lg.getAsMap();

            lg.close();
        }

        /**
         * Constructs a new DatabaseInformationFull instance. <p>
         *
         * @param db the database for which to produce system tables.
         */
        public DatabaseInformationFull(Database db)
            : base(db)
        {

        }

        /**
         * Retrieves the system table corresponding to the specified index. <p>
         *
         * @param tableIndex index identifying the system table to generate
         * @return the system table corresponding to the specified index
         */
        protected override  Table generateTable(int tableIndex)
        {

            switch (tableIndex)
            {

                case ID_SYSTEM_UDTS:
                    return SYSTEM_UDTS();

                case ID_SYSTEM_VERSIONCOLUMNS:
                    return SYSTEM_VERSIONCOLUMNS();

                // HSQLDB-specific
                case ID_SYSTEM_CACHEINFO:
                    return SYSTEM_CACHEINFO();

                case ID_SYSTEM_SESSIONINFO:
                    return SYSTEM_SESSIONINFO();

                case ID_SYSTEM_PROPERTIES:
                    return SYSTEM_PROPERTIES();

                case ID_SYSTEM_PROCEDURECOLUMNS:
                    return SYSTEM_PROCEDURECOLUMNS();

                case ID_SYSTEM_PROCEDURES:
                    return SYSTEM_PROCEDURES();

                case ID_SYSTEM_SESSIONS:
                    return SYSTEM_SESSIONS();

                case ID_SYSTEM_TEXTTABLES:
                    return SYSTEM_TEXTTABLES();

                // SQL views
                case ID_ADMINISTRABLE_ROLE_AUTHORIZATIONS:
                    return ADMINISTRABLE_ROLE_AUTHORIZATIONS();

                case ID_APPLICABLE_ROLES:
                    return APPLICABLE_ROLES();

                case ID_ASSERTIONS:
                    return ASSERTIONS();

                case ID_AUTHORIZATIONS:
                    return AUTHORIZATIONS();

                case ID_CHARACTER_SETS:
                    return CHARACTER_SETS();

                case ID_CHECK_CONSTRAINT_ROUTINE_USAGE:
                    return CHECK_CONSTRAINT_ROUTINE_USAGE();

                case ID_CHECK_CONSTRAINTS:
                    return CHECK_CONSTRAINTS();

                case ID_COLLATIONS:
                    return COLLATIONS();

                case ID_COLUMN_COLUMN_USAGE:
                    return COLUMN_COLUMN_USAGE();

                case ID_COLUMN_DOMAIN_USAGE:
                    return COLUMN_DOMAIN_USAGE();

                case ID_COLUMN_UDT_USAGE:
                    return COLUMN_UDT_USAGE();

                case ID_CONSTRAINT_COLUMN_USAGE:
                    return CONSTRAINT_COLUMN_USAGE();

                case ID_CONSTRAINT_TABLE_USAGE:
                    return CONSTRAINT_TABLE_USAGE();

                case ID_COLUMNS:
                    return COLUMNS();

                case ID_DATA_TYPE_PRIVILEGES:
                    return DATA_TYPE_PRIVILEGES();

                case ID_DOMAIN_CONSTRAINTS:
                    return DOMAIN_CONSTRAINTS();

                case ID_DOMAINS:
                    return DOMAINS();

                case ID_ENABLED_ROLES:
                    return ENABLED_ROLES();

                case ID_ASSEMBLY_ASSEMBLY_USAGE:
                    return ASSEMBLY_ASSEMBLY_USAGE();

                case ID_ASSEMBLIES:
                    return ASSEMBLIES();

                case ID_KEY_COLUMN_USAGE:
                    return KEY_COLUMN_USAGE();

                case ID_METHOD_SPECIFICATIONS:
                    return METHOD_SPECIFICATIONS();

                case ID_MODULE_COLUMN_USAGE:
                    return MODULE_COLUMN_USAGE();

                case ID_MODULE_PRIVILEGES:
                    return MODULE_PRIVILEGES();

                case ID_MODULE_TABLE_USAGE:
                    return MODULE_TABLE_USAGE();

                case ID_MODULES:
                    return MODULES();

                case ID_PARAMETERS:
                    return PARAMETERS();

                case ID_REFERENTIAL_CONSTRAINTS:
                    return REFERENTIAL_CONSTRAINTS();

                case ID_ROLE_AUTHORIZATION_DESCRIPTORS:
                    return ROLE_AUTHORIZATION_DESCRIPTORS();

                case ID_ROLE_COLUMN_GRANTS:
                    return ROLE_COLUMN_GRANTS();

                case ID_ROLE_ROUTINE_GRANTS:
                    return ROLE_ROUTINE_GRANTS();

                case ID_ROLE_TABLE_GRANTS:
                    return ROLE_TABLE_GRANTS();

                case ID_ROLE_USAGE_GRANTS:
                    return ROLE_USAGE_GRANTS();

                case ID_ROLE_UDT_GRANTS:
                    return ROLE_UDT_GRANTS();

                case ID_ROUTINE_COLUMN_USAGE:
                    return ROUTINE_COLUMN_USAGE();

                case ID_ROUTINE_ASSEMBLY_USAGE:
                    return ROUTINE_ASSEMBLY_USAGE();

                case ID_ROUTINE_PRIVILEGES:
                    return ROUTINE_PRIVILEGES();

                case ID_ROUTINE_ROUTINE_USAGE:
                    return ROUTINE_ROUTINE_USAGE();

                case ID_ROUTINE_SEQUENCE_USAGE:
                    return ROUTINE_SEQUENCE_USAGE();

                case ID_ROUTINE_TABLE_USAGE:
                    return ROUTINE_TABLE_USAGE();

                case ID_ROUTINES:
                    return ROUTINES();

                case ID_SCHEMATA:
                    return SCHEMATA();

                case ID_SEQUENCES:
                    return SEQUENCES();

                case ID_SQL_FEATURES:
                    return SQL_FEATURES();

                case ID_SQL_IMPLEMENTATION_INFO:
                    return SQL_IMPLEMENTATION_INFO();

                case ID_SQL_PACKAGES:
                    return SQL_PACKAGES();

                case ID_SQL_PARTS:
                    return SQL_PARTS();

                case ID_SQL_SIZING:
                    return SQL_SIZING();

                case ID_SQL_SIZING_PROFILES:
                    return SQL_SIZING_PROFILES();

                case ID_TABLE_CONSTRAINTS:
                    return TABLE_CONSTRAINTS();

                case ID_TABLES:
                    return TABLES();

                case ID_TRANSLATIONS:
                    return TRANSLATIONS();

                case ID_TRIGGERED_UPDATE_COLUMNS:
                    return TRIGGERED_UPDATE_COLUMNS();

                case ID_TRIGGER_COLUMN_USAGE:
                    return TRIGGER_COLUMN_USAGE();

                case ID_TRIGGER_ROUTINE_USAGE:
                    return TRIGGER_ROUTINE_USAGE();

                case ID_TRIGGER_SEQUENCE_USAGE:
                    return TRIGGER_SEQUENCE_USAGE();

                case ID_TRIGGER_TABLE_USAGE:
                    return TRIGGER_TABLE_USAGE();

                case ID_TRIGGERS:
                    return TRIGGERS();

                case ID_UDT_PRIVILEGES:
                    return UDT_PRIVILEGES();

                case ID_USAGE_PRIVILEGES:
                    return USAGE_PRIVILEGES();

                case ID_USER_DEFINED_TYPES:
                    return USER_DEFINED_TYPES();

                case ID_VIEW_COLUMN_USAGE:
                    return VIEW_COLUMN_USAGE();

                case ID_VIEW_ROUTINE_USAGE:
                    return VIEW_ROUTINE_USAGE();

                case ID_VIEW_TABLE_USAGE:
                    return VIEW_TABLE_USAGE();

                case ID_VIEWS:
                    return VIEWS();

                default:
                    return base.generateTable(tableIndex);
            }
        }

        /**
         * Retrieves a <code>Table</code> object describing the current
         * state of all row caching objects for the accessible
         * tables defined within this database. <p>
         *
         * Currently, the row caching objects for which state is reported are: <p>
         *
         * <OL>
         * <LI> the system-wide <code>Cache</code> object used by CACHED tables.
         * <LI> any <code>TextCache</code> objects in use by [TEMP] TEXT tables.
         * </OL> <p>
         *
         * Each row is a cache object state description with the following
         * columns: <p>
         *
         * <pre class="SqlCodeExample">
         * CACHE_FILE          CHARACTER_DATA   absolute path of cache data file
         * MAX_CACHE_SIZE      INTEGER   maximum allowable cached Row objects
         * MAX_CACHE_BYTE_SIZE INTEGER   maximum allowable size of cached Row objects
         * CACHE_LENGTH        INTEGER   number of data bytes currently cached
         * CACHE_SIZE          INTEGER   number of rows currently cached
         * FREE_BYTES          INTEGER   total bytes in available file allocation units
         * FREE_COUNT          INTEGER   total # of allocation units available
         * FREE_POS            INTEGER   largest file position allocated + 1
         * </pre> <p>
         *
         * <b>Notes:</b> <p>
         *
         * <code>TextCache</code> objects do not maintain a free list because
         * deleted rows are only marked deleted and never reused. As such, the
         * columns FREE_BYTES, SMALLEST_FREE_ITEM, LARGEST_FREE_ITEM, and
         * FREE_COUNT are always reported as zero for rows reporting on
         * <code>TextCache</code> objects. <p>
         *
         * Currently, CACHE_SIZE, FREE_BYTES, SMALLEST_FREE_ITEM, LARGEST_FREE_ITEM,
         * FREE_COUNT and FREE_POS are the only dynamically changing values.
         * All others are constant for the life of a cache object. In a future
         * release, other column values may also change over the life of a cache
         * object, as SQL syntax may eventually be introduced to allow runtime
         * modification of certain cache properties. <p>
         *
         * @return a description of the current state of all row caching
         *      objects associated with the accessible tables of the database
         */
        Table SYSTEM_CACHEINFO()
        {

            Table t = sysTables[ID_SYSTEM_CACHEINFO];

            if (t == null)
            {
                t = createBlankTable(sysTableHsqlNames[ID_SYSTEM_CACHEINFO]);

                addColumn(t, "CACHE_FILE", CHARACTER_DATA);          // not null
                addColumn(t, "MAX_CACHE_COUNT", CARDINAL_NUMBER);    // not null
                addColumn(t, "MAX_CACHE_BYTES", CARDINAL_NUMBER);    // not null
                addColumn(t, "CACHE_SIZE", CARDINAL_NUMBER);         // not null
                addColumn(t, "CACHE_BYTES", CARDINAL_NUMBER);        // not null
                addColumn(t, "FILE_FREE_BYTES", CARDINAL_NUMBER);    // not null
                addColumn(t, "FILE_FREE_COUNT", CARDINAL_NUMBER);    // not null
                addColumn(t, "FILE_FREE_POS", CARDINAL_NUMBER);      // not null

                QNameManager.QName name = QNameManager.newInfoSchemaObjectName(
                    sysTableHsqlNames[ID_SYSTEM_CACHEINFO].name, false,
                    SchemaObjectTypes.INDEX);

                t.createPrimaryKey(name, new int[] { 0 }, true);

                return t;
            }

            // column number mappings
            int icache_file = 0;
            int imax_cache_sz = 1;
            int imax_cache_bytes = 2;
            int icache_size = 3;
            int icache_length = 4;
            int ifree_bytes = 5;
            int ifree_count = 6;
            int ifree_pos = 7;

            //
            PersistentStore store = database.persistentStoreCollection.getStore(t);
            DataFileCache cache = null;
            Object[] row;
            HashSet cacheSet;
            Iterator caches;
            Iterator tables;
            Table table;
            //int iFreeBytes;
            //int iLargestFreeItem;
            //long lSmallestFreeItem;

            // Initialization
            cacheSet = new HashSet();

            // dynamic system tables are never cached
            tables =
                database.schemaManager.databaseObjectIterator(SchemaObjectTypes.TABLE);

            while (tables.hasNext())
            {
                table = (Table)tables.next();

                PersistentStore currentStore =
                    database.persistentStoreCollection.getStore(t);

                if (session.getGrantee().isFullyAccessibleByRole(
                        table.getName()))
                {
                    if (currentStore != null)
                    {
                        cache = currentStore.getCache();
                    }

                    if (cache != null)
                    {
                        cacheSet.add(cache);
                    }
                }
            }

            caches = cacheSet.iterator();

            // Do it.
            while (caches.hasNext())
            {
                cache = (DataFileCache)caches.next();
                row = t.getEmptyRowData();
                row[icache_file] = FileUtil.GetDefaultInstance().CanonicalOrAbsolutePath(
                    cache.getFileName());
                row[imax_cache_sz] = (cache.capacity());
                row[imax_cache_bytes] = (long)(cache.bytesCapacity());
                row[icache_size] = (cache.getCachedObjectCount());
                row[icache_length] =
                    (long)(cache.getTotalCachedBlockSize());
                row[ifree_bytes] = (cache.getTotalFreeBlockSize());
                row[ifree_count] = (cache.getFreeBlockCount());
                row[ifree_pos] = (long)(cache.getFileFreePos());

                t.insertSys(store, row);
            }

            return t;
        }

        /**
         * Retrieves a <code>Table</code> object describing the
         * return, parameter and result columns of the accessible
         * routines defined within this database.<p>
         *
         * Each row is a procedure column description with the following
         * columns: <p>
         *
         * <pre class="SqlCodeExample">
         * PROCEDURE_CAT   VARCHAR   routine catalog
         * PROCEDURE_SCHEM VARCHAR   routine schema
         * PROCEDURE_NAME  VARCHAR   routine name
         * COLUMN_NAME     VARCHAR   column/parameter name
         * COLUMN_TYPE     SMALLINT  kind of column/parameter
         * DATA_TYPE       SMALLINT  SQL type from DITypes
         * TYPE_NAME       VARCHAR   SQL type name
         * PRECISION       INTEGER   precision (length) of type
         * LENGTH          INTEGER   transfer size, in bytes, if definitely known
         *                           (roughly equivalent to BUFFER_SIZE for table
         *                           columns)
         * SCALE           SMALLINT  scale
         * RADIX           SMALLINT  radix
         * NULLABLE        SMALLINT  can column contain NULL?
         * REMARKS         VARCHAR   explanatory comment on column
         * // JDBC 4.0
         * COLUMN_DEF        VARCHAR The default column value.
         *                           The string NULL (not enclosed in quotes)
         *                           - If NULL was specified as the default value
         *                           TRUNCATE (not enclosed in quotes)
         *                           - If the specified default value cannot be
         *                           represented without truncation
         *                           NULL
         *                           - If a default value was not specified
         * SQL_DATA_TYPE     INTEGER CLI type list from SQL 2003 Table 37,
         *                           tables 6-9 Annex A1, and/or addendums in other
         *                           documents, such as:
         *                           SQL 2003 Part 9: Management of External Data (SQL/MED) : DATALINK
         *                           SQL 2003 Part 14: XML-Related Specifications (SQL/XML) : XML
         * SQL_DATETIME_SUB  INTEGER SQL 2003 CLI datetime/interval subcode.
         * CHAR_OCTET_LENGTH INTEGER The maximum length of binary and character
         *                           based columns.  For any other datatype the
         *                           returned value is a NULL
         * ORDINAL_POSITION  INTEGER The ordinal position, starting from 1, for the
         *                           input and output parameters for a procedure.
         *                           A value of 0 is returned if this row describes
         *                           the procedure's return value.
         * IS_NULLABLE       VARCHAR ISO rules are used to determinte the nulliblity
         *                           for a column.
         *
         *                           YES (enclosed in quotes)  --- if the column can include NULLs
         *                           NO  (enclosed in quotes)  --- if the column cannot include NULLs
         *                           empty string              --- if the nullability for the column is unknown
         *
         * SPECIFIC_NAME     VARCHAR The name which uniquely identifies this
         *                           procedure within its schema.
         *                           Typically (but not restricted to) a
         *                           fully qualified Java Method name and
         *                           signature
         * // HSQLDB extension
         * JDBC_SEQ          INTEGER The JDBC-specified order within
         *                           runs of PROCEDURE_SCHEM, PROCEDURE_NAME,
         *                           SPECIFIC_NAME, which is:
         *
         *                           return value (0), if any, first, followed
         *                           by the parameter descriptions in call order
         *                           (1..n1), followed by the result column
         *                           descriptions in column number order
         *                           (n1 + 1..n1 + n2)
         * </pre> <p>
         *
         * @return a <code>Table</code> object describing the
         *        return, parameter and result columns
         *        of the accessible routines defined
         *        within this database.
         */
        Table SYSTEM_PROCEDURECOLUMNS()
        {

            Table t = sysTables[ID_SYSTEM_PROCEDURECOLUMNS];

            if (t == null)
            {
                t = createBlankTable(sysTableHsqlNames[ID_SYSTEM_PROCEDURECOLUMNS]);

                // ----------------------------------------------------------------
                // required
                // ----------------------------------------------------------------
                addColumn(t, "PROCEDURE_CAT", SQL_IDENTIFIER);          // 0
                addColumn(t, "PROCEDURE_SCHEM", SQL_IDENTIFIER);        // 1
                addColumn(t, "PROCEDURE_NAME", SQL_IDENTIFIER);         // not null
                addColumn(t, "COLUMN_NAME", SQL_IDENTIFIER);            // not null
                addColumn(t, "COLUMN_TYPE", SqlType.SQL_INTEGER);         // not null
                addColumn(t, "DATA_TYPE", SqlType.SQL_SMALLINT);           // not null
                addColumn(t, "TYPE_NAME", SQL_IDENTIFIER);              // not null
                addColumn(t, "PRECISION", SqlType.SQL_INTEGER);            // 7
                addColumn(t, "LENGTH", SqlType.SQL_INTEGER);               // 8
                addColumn(t, "SCALE", SqlType.SQL_INTEGER);               // 9
                addColumn(t, "RADIX", SqlType.SQL_INTEGER);               // 10
                addColumn(t, "NULLABLE", SqlType.SQL_INTEGER);            // not null
                addColumn(t, "REMARKS", CHARACTER_DATA);                // 12

                // ----------------------------------------------------------------
                // JDBC 4.0
                // ----------------------------------------------------------------
                addColumn(t, "COLUMN_DEF", CHARACTER_DATA);             // 13
                addColumn(t, "SQL_DATA_TYPE", SqlType.SQL_INTEGER);        // 14
                addColumn(t, "SQL_DATETIME_SUB", SqlType.SQL_INTEGER);     // 15
                addColumn(t, "CHAR_OCTET_LENGTH", SqlType.SQL_INTEGER);    // 16
                addColumn(t, "ORDINAL_POSITION", SqlType.SQL_INTEGER);     // 17
                addColumn(t, "IS_NULLABLE", CHARACTER_DATA);            // 18
                addColumn(t, "SPECIFIC_NAME", SQL_IDENTIFIER);          // 19

                // order: PROCEDURE_SCHEM, PROCEDURE_NAME, SPECIFIC_NAME, ORDINAL_POSITION
                //
                QNameManager.QName name = QNameManager.newInfoSchemaObjectName(
                    sysTableHsqlNames[ID_SYSTEM_PROCEDURECOLUMNS].name, false,
                    SchemaObjectTypes.INDEX);

                t.createPrimaryKey(name, new int[] {
                0, 1, 2, 19, 17
            }, false);

                return t;
            }

            PersistentStore store = database.persistentStoreCollection.getStore(t);

            // column number mappings
            int specific_cat = 0;
            int specific_schem = 1;
            int procedure_name = 2;
            int parameter_name = 3;
            int parameter_mode = 4;
            int data_type_sql_id = 5;
            int data_type = 6;
            int numeric_precision = 7;
            //int byte_length = 8;
            int numeric_scale = 9;
            int numeric_precision_radix = 10;
            int nullable = 11;
            //int remark = 12;
            //int default_val = 13;
            int sql_data_type = 14;
            //int sql_datetime_sub = 15;
            int character_octet_length = 16;
            int ordinal_position = 17;
            int is_nullable = 18;
            int specific_name = 19;

            // intermediate holders
            int columnCount;
            Iterator routines;
            RoutineSchema routineSchema;
            Routine routine;
            Object[] row;
            SqlType type;

            // Initialization
            routines = database.schemaManager.databaseObjectIterator(
                SchemaObjectTypes.ROUTINE);

            while (routines.hasNext())
            {
                routineSchema = (RoutineSchema)routines.next();

                if (!session.getGrantee().isAccessible(routineSchema))
                {
                    continue;
                }

                Routine[] specifics = routineSchema.getSpecificRoutines();

                for (int i = 0; i < specifics.Length; i++)
                {
                    routine = specifics[i];
                    columnCount = routine.getParameterCount();

                    for (int j = 0; j < columnCount; j++)
                    {
                        ColumnSchema column = routine.getParameter(j);

                        type = column.getDataType();
                        row = t.getEmptyRowData();
                        row[specific_cat] = database.getCatalogName().originalName;
                        row[specific_schem] = routine.getSchemaName().originalName;
                        row[specific_name] = routine.getSpecificName().originalName;
                        row[procedure_name] = routine.getName().originalName;
                        row[parameter_name] = column.getName().originalName;
                        row[ordinal_position] = (j + 1);
                        row[parameter_mode] =
                            (int)(column.getParameterMode());
                        row[data_type] = type.getFullNameString();
                        row[data_type_sql_id] =
                            (type.getAdoTypeCode());
                        row[numeric_precision] = 0;
                        row[character_octet_length] = 0;

                        if (type.isCharacterType())
                        {
                            row[numeric_precision] =
                                (type.getAdoPrecision());

                            // this is length not octet_length, for character columns
                            row[character_octet_length] =
                                (type.getAdoPrecision());
                        }

                        if (type.isBinaryType())
                        {
                            row[numeric_precision] =
                                (type.getAdoPrecision());
                            row[character_octet_length] =
                                (type.getAdoPrecision());
                        }

                        if (type.isNumberType())
                        {
                            row[numeric_precision] = (
                                ((NumberType)type).getNumericPrecisionInRadix());
                            row[numeric_precision_radix] =
                                (type.getPrecisionRadix());

                            if (type.isExactNumberType())
                            {
                                row[numeric_scale] = (type.scale);
                            }
                        }

                        if (type.isDateTimeType())
                        {
                            int size = (int)column.getDataType().displaySize();

                            row[numeric_precision] = (size);
                        }

                        row[sql_data_type] =
                            (column.getDataType().typeCode);
                        row[nullable] = (int)(column.getNullability());
                        row[is_nullable] = column.isNullable() ? "YES"
                                                               : "NO";

                        t.insertSys(store, row);
                    }
                }
            }

            return t;
        }

        /**
         * Retrieves a <code>Table</code> object describing the accessible
         * routines defined within this database.
         *
         * Each row is a procedure description with the following
         * columns: <p>
         *
         * <pre class="SqlCodeExample">
         * PROCEDURE_CAT     VARCHAR   catalog in which routine is defined
         * PROCEDURE_SCHEM   VARCHAR   schema in which routine is defined
         * PROCEDURE_NAME    VARCHAR   simple routine identifier
         * COL_4             INTEGER   unused
         * COL_5             INTEGER   unused
         * COL_6             INTEGER   unused
         * REMARKS           VARCHAR   explanatory comment on the routine
         * PROCEDURE_TYPE    SMALLINT  { Unknown | No Result | Returns Result }
         * // JDBC 4.0
         * SPECIFIC_NAME     VARCHAR   The name which uniquely identifies this
         *                             procedure within its schema.
         *                             typically (but not restricted to) a
         *                             fully qualified Java Method name
         *                             and signature.
         * // HSQLDB extension
         * ORIGIN            VARCHAR   {ALIAS |
         *                             [BUILTIN | USER DEFINED] ROUTINE |
         *                             [BUILTIN | USER DEFINED] TRIGGER |
         *                              ...}
         * </pre> <p>
         *
         * @return a <code>Table</code> object describing the accessible
         *        routines defined within the this database
         */
        Table SYSTEM_PROCEDURES()
        {

            Table t = sysTables[ID_SYSTEM_PROCEDURES];

            if (t == null)
            {
                t = createBlankTable(sysTableHsqlNames[ID_SYSTEM_PROCEDURES]);

                // ----------------------------------------------------------------
                // required
                // ----------------------------------------------------------------
                addColumn(t, "PROCEDURE_CAT", SQL_IDENTIFIER);        // 0
                addColumn(t, "PROCEDURE_SCHEM", SQL_IDENTIFIER);      // 1
                addColumn(t, "PROCEDURE_NAME", SQL_IDENTIFIER);       // 2
                addColumn(t, "COL_4", SqlType.SQL_INTEGER);              // 3
                addColumn(t, "COL_5", SqlType.SQL_INTEGER);              // 4
                addColumn(t, "COL_6", SqlType.SQL_INTEGER);              // 5
                addColumn(t, "REMARKS", CHARACTER_DATA);              // 6

                // basically: function (returns result), procedure (no return value)
                // or unknown (say, a trigger callout routine)
                addColumn(t, "PROCEDURE_TYPE", SqlType.SQL_SMALLINT);    // 7

                // ----------------------------------------------------------------
                // JDBC 4.0
                // ----------------------------------------------------------------
                addColumn(t, "SPECIFIC_NAME", SQL_IDENTIFIER);        // 8

                // ----------------------------------------------------------------
                // order: PROCEDURE_CAT, PROCEDURE_SCHEM, PROCEDURE_NAME, SPECIFIC_NAME
                QNameManager.QName name = QNameManager.newInfoSchemaObjectName(
                    sysTableHsqlNames[ID_SYSTEM_PROCEDURES].name, false,
                    SchemaObjectTypes.INDEX);

                t.createPrimaryKey(name, new int[] {
                0, 1, 2, 8
            }, false);

                return t;
            }

            PersistentStore store = database.persistentStoreCollection.getStore(t);

            //
            Session sys = database.sessionManager.newSysSession(
                SqlInvariants.INFORMATION_SCHEMA_QNAME, session.getUser());
            String sql = (String)statementMap.get("/*system_procedures*/");
            Result rs = sys.executeDirectStatement(sql);

            /*
                    RowSetNavigator nav = rs.getNavigator();

                    while (nav.hasNext()) {
                        Object[] row    = nav.getNext();
                        String   schema = (String) row[1];
                        String   name   = (String) row[2];
                        RoutineSchema routineSchema =
                            (RoutineSchema) database.schemaManager.getSchemaObject(name,
                                schema, SchemaObjectTypes.ROUTINE);
                        Routine[] routines = routineSchema.getSpecificRoutines();

                        for (int i = 0; i < routines.Length; i++) {
                            if (row[8].Equals(routines[i].getSpecificName().name)) {
                                row[3] = (
                                    routines[i].getParameterCount(
                                        SchemaObjectTypes.ParameterModes.PARAM_IN));
                                row[4] = (
                                    routines[i].getParameterCount(
                                        SchemaObjectTypes.ParameterModes.PARAM_OUT));
                            }
                        }
                    }

                    nav.reset();
            */
            t.insertSys(store, rs);
            sys.close();

            return t;
        }

        /**
         * Retrieves a <code>Table</code> object describing the capabilities
         * and operating parameter properties for the engine hosting this
         * database, as well as their applicability in terms of scope and
         * name space. <p>
         *
         * Reported properties include certain predefined <code>Database</code>
         * properties file values as well as certain database scope
         * attributes. <p>
         *
         * It is intended that all <code>Database</code> attributes and
         * properties that can be set via the database properties file,
         * JDBC connection properties or SQL SET/ALTER statements will
         * eventually be reported here or, where more applicable, in an
         * ANSI/ISO conforming feature info base table in the defintion
         * schema. <p>
         *
         * Currently, the database properties reported are: <p>
         *
         * <OL>
         *     <LI>hsqldb.cache_file_scale - the scaling factor used to translate data and index structure file pointers
         *     <LI>hsqldb.cache_scale - base-2 exponent scaling allowable cache row count
         *     <LI>hsqldb.cache_size_scale - base-2 exponent scaling allowable cache byte count
         *     <LI>hsqldb.cache_version -
         *     <LI>hsqldb.catalogs - whether to report the database catalog (database uri)
         *     <LI>hsqldb.compatible_version -
         *     <LI>hsqldb.files_readonly - whether the database is in files_readonly mode
         *     <LI>hsqldb.gc_interval - # new records forcing gc ({0|NULL}=>never)
         *     <LI>hsqldb.max_nio_scale - scale factor for cache nio mapped buffers
         *     <LI>hsqldb.nio_data_file - whether cache uses nio mapped buffers
         *     <LI>hsqldb.original_version -
         *     <LI>sql.enforce_strict_size - column length specifications enforced strictly (raise exception on overflow)?
         *     <LI>textdb.all_quoted - default policy regarding whether to quote all character field values
         *     <LI>textdb.cache_scale - base-2 exponent scaling allowable cache row count
         *     <LI>textdb.cache_size_scale - base-2 exponent scaling allowable cache byte count
         *     <LI>textdb.encoding - default TEXT table file encoding
         *     <LI>textdb.fs - default field separator
         *     <LI>textdb.vs - default varchar field separator
         *     <LI>textdb.lvs - default long varchar field separator
         *     <LI>textdb.ignore_first - default policy regarding whether to ignore the first line
         *     <LI>textdb.quoted - default policy regarding treatement character field values that _may_ require quoting
         *     <LI>IGNORECASE - create table VARCHAR_IGNORECASE?
         *     <LI>LOGSIZSE - # bytes to which REDO log grows before auto-checkpoint
         *     <LI>REFERENTIAL_INTEGITY - currently enforcing referential integrity?
         *     <LI>SCRIPTFORMAT - 0 : TEXT, 1 : BINARY, ...
         *     <LI>WRITEDELAY - does REDO log currently use buffered write strategy?
         * </OL> <p>
         *
         * @return table describing database and session operating parameters
         *      and capabilities
         */
        Table SYSTEM_PROPERTIES()
        {

            Table t = sysTables[ID_SYSTEM_PROPERTIES];

            if (t == null)
            {
                t = createBlankTable(sysTableHsqlNames[ID_SYSTEM_PROPERTIES]);

                addColumn(t, "PROPERTY_SCOPE", CHARACTER_DATA);
                addColumn(t, "PROPERTY_NAMESPACE", CHARACTER_DATA);
                addColumn(t, "PROPERTY_NAME", CHARACTER_DATA);
                addColumn(t, "PROPERTY_VALUE", CHARACTER_DATA);
                addColumn(t, "PROPERTY_CLASS", CHARACTER_DATA);

                // order PROPERTY_SCOPE, PROPERTY_NAMESPACE, PROPERTY_NAME
                // true PK
                QNameManager.QName name = QNameManager.newInfoSchemaObjectName(
                    sysTableHsqlNames[ID_SYSTEM_PROPERTIES].name, false,
                    SchemaObjectTypes.INDEX);

                t.createPrimaryKey(name, new int[] {
                0, 1, 2
            }, true);

                return t;
            }

            // column number mappings
            int iscope = 0;
            int ins = 1;
            int iname = 2;
            int ivalue = 3;
            int iclass = 4;

            //
            PersistentStore store = database.persistentStoreCollection.getStore(t);

            // calculated column values
            String scope;
            String nameSpace;

            // intermediate holders
            Object[] row;
            EffiProzDatabaseProperties props;

            // First, we want the names and values for
            // all JDBC capabilities constants
            scope = "SESSION";
            props = database.getProperties();
            nameSpace = "database.properties";

            // bool properties

            Iterator it =props.getUserDefinedPropertyData().iterator();
            while (it.hasNext())
            {
                object[] metaData = (object[])it.next();
                row = t.getEmptyRowData();
                row[iscope] = scope;
                row[ins] = nameSpace;
                row[iname] = metaData[EffiProzDatabaseProperties.indexName];
                row[ivalue] = props.getProperty((String)row[iname]);
                row[iclass] = metaData[EffiProzDatabaseProperties.indexClass];

                t.insertSys(store, row);
            }

            row = t.getEmptyRowData();
            row[iscope] = scope;
            row[ins] = nameSpace;
            row[iname] = "SCRIPT FORMAT";

            try
            {
                row[ivalue] =
                    ScriptWriterBase
                        .LIST_SCRIPT_FORMATS[database.logger.getScriptType()];
            }
            catch (Exception) { }

            row[iclass] = "String";

            t.insertSys(store, row);

            // write delay
            row = t.getEmptyRowData();
            row[iscope] = scope;
            row[ins] = nameSpace;
            row[iname] = "WRITE DELAY";
            row[ivalue] = "" + database.logger.getWriteDelay();
            row[iclass] = "Integer";

            t.insertSys(store, row);

            // ignore case
            row = t.getEmptyRowData();
            row[iscope] = scope;
            row[ins] = nameSpace;
            row[iname] = "IGNORECASE";
            row[ivalue] = database.isIgnoreCase() ? "true"
                                                  : "false";
            row[iclass] = "Boolean";

            t.insertSys(store, row);

            // referential integrity
            row = t.getEmptyRowData();
            row[iscope] = scope;
            row[ins] = nameSpace;
            row[iname] = "REFERENTIAL INTEGRITY";
            row[ivalue] = database.isReferentialIntegrity() ? "true"
                                                            : "false";
            row[iclass] = "Boolean";

            t.insertSys(store, row);

            return t;
        }

        /**
         * Retrieves a <code>Table</code> object describing attributes
         * for the calling session context.<p>
         *
         * The rows report the following {key,value} pairs:<p>
         *
         * <pre class="SqlCodeExample">
         * KEY (VARCHAR)       VALUE (VARCHAR)
         * ------------------- ---------------
         * SESSION_ID          the id of the calling session
         * AUTOCOMMIT          YES: session is in autocommit mode, else NO
         * USER                the name of user connected in the calling session
         * (was READ_ONLY)
         * SESSION_READONLY    TRUE: session is in read-only mode, else FALSE
         * (new)
         * DATABASE_READONLY   TRUE: database is in read-only mode, else FALSE
         * MAXROWS             the MAXROWS setting in the calling session
         * DATABASE            the name of the database
         * IDENTITY            the last identity value used by calling session
         * </pre>
         *
         * <b>Note:</b>  This table <em>may</em> become deprecated in a future
         * release, as the information it reports now duplicates information
         * reported in the newer SYSTEM_SESSIONS and SYSTEM_PROPERTIES
         * tables. <p>
         *
         * @return a <code>Table</code> object describing the
         *        attributes of the connection associated
         *        with the current execution context
         */
        Table SYSTEM_SESSIONINFO()
        {

            Table t = sysTables[ID_SYSTEM_SESSIONINFO];

            if (t == null)
            {
                t = createBlankTable(sysTableHsqlNames[ID_SYSTEM_SESSIONINFO]);

                addColumn(t, "KEY", CHARACTER_DATA);      // not null
                addColumn(t, "VALUE", CHARACTER_DATA);    // not null

                QNameManager.QName name = QNameManager.newInfoSchemaObjectName(
                    sysTableHsqlNames[ID_SYSTEM_SESSIONINFO].name, false,
                    SchemaObjectTypes.INDEX);

                t.createPrimaryKey(name, new int[] { 0 }, true);

                return t;
            }

            PersistentStore store = database.persistentStoreCollection.getStore(t);
            Object[] row;

            row = t.getEmptyRowData();
            row[0] = "SESSION ID";
            row[1] = (session.getId()).ToString();

            t.insertSys(store, row);

            row = t.getEmptyRowData();
            row[0] = "AUTOCOMMIT";
            row[1] = session.isAutoCommit() ? Tokens.T_TRUE
                                            : Tokens.T_FALSE;

            t.insertSys(store, row);

            row = t.getEmptyRowData();
            row[0] = "USER";
            row[1] = session.getUsername();

            t.insertSys(store, row);

            row = t.getEmptyRowData();
            row[0] = "SESSION READONLY";
            row[1] = session.isReadOnlyDefault() ? Tokens.T_TRUE
                                                 : Tokens.T_FALSE;

            t.insertSys(store, row);

            row = t.getEmptyRowData();
            row[0] = "DATABASE READONLY";
            row[1] = database.isReadOnly() ? Tokens.T_TRUE
                                           : Tokens.T_FALSE;

            t.insertSys(store, row);

            // fredt - value set by SET MAXROWS in SQL, not Statement.setMaxRows()
            row = t.getEmptyRowData();
            row[0] = "MAXROWS";
            row[1] = (session.getSQLMaxRows()).ToString();

            t.insertSys(store, row);

            row = t.getEmptyRowData();
            row[0] = "DATABASE";
            row[1] = database.getURI();

            t.insertSys(store, row);

            row = t.getEmptyRowData();
            row[0] = "IDENTITY";
            row[1] = (session.getLastIdentity()).ToString();

            t.insertSys(store, row);

            row = t.getEmptyRowData();
            row[0] = "CURRENT SCHEMA";
            row[1] = (session.getSchemaName(null)).ToString();

            t.insertSys(store, row);

            return t;
        }

        /**
         * Retrieves a <code>Table</code> object describing all visible
         * sessions. ADMIN users see *all* sessions
         * while non-admin users see only their own session.<p>
         *
         * Each row is a session state description with the following columns: <p>
         *
         * <pre class="SqlCodeExample">
         * SESSION_ID         INTEGER   session identifier
         * CONNECTED          TIMESTAMP time at which session was created
         * USER_NAME          VARCHAR   db user name of current session user
         * IS_ADMIN           BOOLEAN   is session user an admin user?
         * AUTOCOMMIT         BOOLEAN   is session in autocommit mode?
         * READONLY           BOOLEAN   is session in read-only mode?
         * MAXROWS            INTEGER   session's MAXROWS setting
         * LAST_IDENTITY      INTEGER   last identity value used by this session
         * TRANSACTION_SIZE   INTEGER   # of undo items in current transaction
         * SCHEMA             VARCHAR   current schema for session
         * </pre> <p>
         *
         * @return a <code>Table</code> object describing all visible
         *      sessions
         */
        Table SYSTEM_SESSIONS()
        {

            Table t = sysTables[ID_SYSTEM_SESSIONS];

            if (t == null)
            {
                t = createBlankTable(sysTableHsqlNames[ID_SYSTEM_SESSIONS]);

                addColumn(t, "SESSION_ID", CARDINAL_NUMBER);
                addColumn(t, "CONNECTED", TIME_STAMP);
                addColumn(t, "USER_NAME", SQL_IDENTIFIER);
                addColumn(t, "IS_ADMIN", SqlType.SQL_BOOLEAN);
                addColumn(t, "AUTOCOMMIT", SqlType.SQL_BOOLEAN);
                addColumn(t, "READONLY", SqlType.SQL_BOOLEAN);
                addColumn(t, "MAXROWS", CARDINAL_NUMBER);

                // Note: some sessions may have a NULL LAST_IDENTITY value
                addColumn(t, "LAST_IDENTITY", CARDINAL_NUMBER);
                addColumn(t, "TRANSACTION_SIZE", CARDINAL_NUMBER);
                addColumn(t, "SCHEMA", SQL_IDENTIFIER);

                // order:  SESSION_ID
                // true primary key
                QNameManager.QName name = QNameManager.newInfoSchemaObjectName(
                    sysTableHsqlNames[ID_SYSTEM_SESSIONS].name, false,
                    SchemaObjectTypes.INDEX);

                t.createPrimaryKey(name, new int[] { 0 }, true);

                return t;
            }

            // column number mappings
            int isid = 0;
            int ict = 1;
            int iuname = 2;
            int iis_admin = 3;
            int iautocmt = 4;
            int ireadonly = 5;
            int imaxrows = 6;
            int ilast_id = 7;
            int it_size = 8;
            int it_schema = 9;

            //
            PersistentStore store = database.persistentStoreCollection.getStore(t);

            // intermediate holders
            Session[] sessions;
            Session s;
            Object[] row;

            // Initialisation
            sessions = database.sessionManager.getVisibleSessions(session);

            // Do it.
            for (int i = 0; i < sessions.Length; i++)
            {
                s = sessions[i];
                row = t.getEmptyRowData();
                row[isid] = (long)(s.getId());
                row[ict] = new TimestampData(s.getConnectTime() / 1000);
                row[iuname] = s.getUsername();
                row[iis_admin] = (bool)(s.isAdmin());
                row[iautocmt] = (bool)(s.isAutoCommit());
                row[ireadonly] = (bool)(s.isReadOnlyDefault());
                row[imaxrows] = (s.getSQLMaxRows());
                row[ilast_id] =
                  Convert.ToInt64(s.getLastIdentity());
                row[it_size] = (s.getTransactionSize());
                row[it_schema] = s.getCurrentSchemaHsqlName().originalName;

                t.insertSys(store, row);
            }

            return t;
        }

        /**
         * Retrieves a <code>Table</code> object describing the TEXT TABLE objects
         * defined within this database. The table contains one row for each row
         * in the SYSTEM_TABLES table with a HSQLDB_TYPE of  TEXT . <p>
         *
         * Each row is a description of the attributes that defines its TEXT TABLE,
         * with the following columns:
         *
         * <pre class="SqlCodeExample">
         * TABLE_CAT                 VARCHAR   table's catalog name
         * TABLE_SCHEM               VARCHAR   table's simple schema name
         * TABLE_NAME                VARCHAR   table's simple name
         * DATA_SOURCE_DEFINITION    VARCHAR   the "spec" proption of the table's
         *                                     SET TABLE ... SOURCE DDL declaration
         * FILE_PATH                 VARCHAR   absolute file path.
         * FILE_ENCODING             VARCHAR   endcoding of table's text file
         * FIELD_SEPARATOR           VARCHAR   default field separator
         * VARCHAR_SEPARATOR         VARCAHR   varchar field separator
         * LONGVARCHAR_SEPARATOR     VARCHAR   longvarchar field separator
         * IS_IGNORE_FIRST           BOOLEAN   ignores first line of file?
         * IS_QUOTED                 BOOLEAN   fields are quoted if necessary?
         * IS_ALL_QUOTED             BOOLEAN   all fields are quoted?
         * IS_DESC                   BOOLEAN   read rows starting at end of file?
         * </pre> <p>
         *
         * @return a <code>Table</code> object describing the text attributes
         * of the accessible text tables defined within this database
         *
         */
        Table SYSTEM_TEXTTABLES()
        {

            Table t = sysTables[ID_SYSTEM_TEXTTABLES];

            if (t == null)
            {
                t = createBlankTable(sysTableHsqlNames[ID_SYSTEM_TEXTTABLES]);

                addColumn(t, "TABLE_CAT", SQL_IDENTIFIER);
                addColumn(t, "TABLE_SCHEM", SQL_IDENTIFIER);
                addColumn(t, "TABLE_NAME", SQL_IDENTIFIER);    // not null
                addColumn(t, "DATA_SOURCE_DEFINTION", CHARACTER_DATA);
                addColumn(t, "FILE_PATH", CHARACTER_DATA);
                addColumn(t, "FILE_ENCODING", CHARACTER_DATA);
                addColumn(t, "FIELD_SEPARATOR", CHARACTER_DATA);
                addColumn(t, "VARCHAR_SEPARATOR", CHARACTER_DATA);
                addColumn(t, "LONGVARCHAR_SEPARATOR", CHARACTER_DATA);
                addColumn(t, "IS_IGNORE_FIRST", SqlType.SQL_BOOLEAN);
                addColumn(t, "IS_ALL_QUOTED", SqlType.SQL_BOOLEAN);
                addColumn(t, "IS_QUOTED", SqlType.SQL_BOOLEAN);
                addColumn(t, "IS_DESC", SqlType.SQL_BOOLEAN);

                // ------------------------------------------------------------
                QNameManager.QName name = QNameManager.newInfoSchemaObjectName(
                    sysTableHsqlNames[ID_SYSTEM_TEXTTABLES].name, false,
                    SchemaObjectTypes.INDEX);

                t.createPrimaryKey(name, new int[] {
                0, 1, 2,
            }, false);

                return t;
            }

            // column number mappings
            int itable_cat = 0;
            int itable_schem = 1;
            int itable_name = 2;
            int idsd = 3;
            int ifile_path = 4;
            int ifile_enc = 5;
            int ifs = 6;
            int ivfs = 7;
            int ilvfs = 8;
            int iif = 9;
            int iiq = 10;
            int iiaq = 11;
            int iid = 12;

            //
            PersistentStore store = database.persistentStoreCollection.getStore(t);

            // intermediate holders
            Iterator tables;
            Table table;
            Object[] row;

            // Initialization
            tables =
                database.schemaManager.databaseObjectIterator(SchemaObjectTypes.TABLE);

            // Do it.
            while (tables.hasNext())
            {
                table = (Table)tables.next();

                PersistentStore currentStore =
                    database.persistentStoreCollection.getStore(t);

                if (!table.isText() || !isAccessibleTable(table))
                {
                    continue;
                }

                row = t.getEmptyRowData();
                row[itable_cat] = database.getCatalogName().originalName;
                row[itable_schem] = table.getSchemaName().originalName;
                row[itable_name] = table.getName().originalName;
                row[idsd] = ((TextTable)table).getDataSource();

                TextCache cache = (TextCache)currentStore.getCache();

                if (cache != null)
                {
                    row[ifile_path] =
                        FileUtil.GetDefaultInstance().CanonicalOrAbsolutePath(
                            cache.getFileName());
                    row[ifile_enc] = cache.stringEncoding;
                    row[ifs] = cache.fs;
                    row[ivfs] = cache.vs;
                    row[ilvfs] = cache.lvs;
                    row[iif] = (bool)(cache.ignoreFirst);
                    row[iiq] = (bool)(cache.isQuoted);
                    row[iiaq] = (bool)(cache.isAllQuoted);
                    row[iid] = ((TextTable)table).isDescDataSource()
                               ? true
                               : false;
                }

                t.insertSys(store, row);
            }

            return t;
        }

        /**
         * Retrieves a <code>Table</code> object describing the accessible
         * user-defined types defined in this database. <p>
         *
         * Schema-specific UDTs may have type JAVA_OBJECT, STRUCT, or DISTINCT.
         *
         * <P>Each row is a UDT descripion with the following columns:
         * <OL>
         *   <LI><B>TYPE_CAT</B> <code>VARCHAR</code> => the type's catalog
         *   <LI><B>TYPE_SCHEM</B> <code>VARCHAR</code> => type's schema
         *   <LI><B>TYPE_NAME</B> <code>VARCHAR</code> => type name
         *   <LI><B>CLASS_NAME</B> <code>VARCHAR</code> => Java class name
         *   <LI><B>DATA_TYPE</B> <code>VARCHAR</code> =>
         *         type value defined in <code>DITypes</code>;
         *         one of <code>JAVA_OBJECT</code>, <code>STRUCT</code>, or
         *        <code>DISTINCT</code>
         *   <LI><B>REMARKS</B> <code>VARCHAR</code> =>
         *          explanatory comment on the type
         *   <LI><B>BASE_TYPE</B><code>SMALLINT</code> =>
         *          type code of the source type of a DISTINCT type or the
         *          type that implements the user-generated reference type of the
         *          SELF_REFERENCING_COLUMN of a structured type as defined in
         *          DITypes (null if DATA_TYPE is not DISTINCT or not
         *          STRUCT with REFERENCE_GENERATION = USER_DEFINED)
         *
         * </OL> <p>
         *
         * @return a <code>Table</code> object describing the accessible
         *      user-defined types defined in this database
         */
        Table SYSTEM_UDTS()
        {

            Table t = sysTables[ID_SYSTEM_UDTS];

            if (t == null)
            {
                t = createBlankTable(sysTableHsqlNames[ID_SYSTEM_UDTS]);

                addColumn(t, "TYPE_CAT", SQL_IDENTIFIER);
                addColumn(t, "TYPE_SCHEM", SQL_IDENTIFIER);
                addColumn(t, "TYPE_NAME", SQL_IDENTIFIER);
                addColumn(t, "CLASS_NAME", CHARACTER_DATA);
                addColumn(t, "DATA_TYPE", SqlType.SQL_INTEGER);
                addColumn(t, "REMARKS", CHARACTER_DATA);
                addColumn(t, "BASE_TYPE", SqlType.SQL_SMALLINT);

                //
                QNameManager.QName name = QNameManager.newInfoSchemaObjectName(
                    sysTableHsqlNames[ID_SYSTEM_UDTS].name, false,
                    SchemaObjectTypes.INDEX);

                t.createPrimaryKey(name, null, false);

                return t;
            }

            PersistentStore store = database.persistentStoreCollection.getStore(t);

            // column number mappings
            int type_catalog = 0;
            int type_schema = 1;
            int type_name = 2;
            int class_name = 3;
            int data_type = 4;
            int remarks = 5;
            int base_type = 6;
            Iterator it =
                database.schemaManager.databaseObjectIterator(SchemaObjectTypes.TYPE);

            while (it.hasNext())
            {
                SqlType distinct = (SqlType)it.next();

                if (!distinct.isDistinctType())
                {
                    continue;
                }

                Object[] data = t.getEmptyRowData();

                data[type_catalog] = database.getCatalogName().originalName;
                data[type_schema] = distinct.getSchemaName().originalName;
                data[type_name] = distinct.getName().originalName;
                data[class_name] = distinct.getCSharpClassName();
                data[data_type] = (Types.DISTINCT);
                data[remarks] = null;
                data[base_type] = (distinct.getAdoTypeCode());

                t.insertSys(store, data);
            }

            return t;
        }

        /**
         * Retrieves a <code>Table</code> object describing the accessible
         * columns that are automatically updated when any value in a row
         * is updated. <p>
         *
         * Each row is a version column description with the following columns: <p>
         *
         * <OL>
         * <LI><B>SCOPE</B> <code>SMALLINT</code> => is not used
         * <LI><B>COLUMN_NAME</B> <code>VARCHAR</code> => column name
         * <LI><B>DATA_TYPE</B> <code>SMALLINT</code> =>
         *        SQL data type from java.sql.Types
         * <LI><B>TYPE_NAME</B> <code>SMALLINT</code> =>
         *       Data source dependent type name
         * <LI><B>COLUMN_SIZE</B> <code>INTEGER</code> => precision
         * <LI><B>BUFFER_LENGTH</B> <code>INTEGER</code> =>
         *        length of column value in bytes
         * <LI><B>DECIMAL_DIGITS</B> <code>SMALLINT</code> => scale
         * <LI><B>PSEUDO_COLUMN</B> <code>SMALLINT</code> =>
         *        is this a pseudo column like an Oracle <code>ROWID</code>:<BR>
         *        (as defined in <code>java.sql.DatabaseMetadata</code>)
         * <UL>
         *    <LI><code>versionColumnUnknown</code> - may or may not be
         *        pseudo column
         *    <LI><code>versionColumnNotPseudo</code> - is NOT a pseudo column
         *    <LI><code>versionColumnPseudo</code> - is a pseudo column
         * </UL>
         * </OL> <p>
         *
         * <B>Note:</B> Currently, the HSQLDB engine does not support version
         * columns, so an empty table is returned. <p>
         *
         * @return a <code>Table</code> object describing the columns
         *        that are automatically updated when any value
         *        in a row is updated
         */
        Table SYSTEM_VERSIONCOLUMNS()
        {

            Table t = sysTables[ID_SYSTEM_VERSIONCOLUMNS];

            if (t == null)
            {
                t = createBlankTable(sysTableHsqlNames[ID_SYSTEM_VERSIONCOLUMNS]);

                // ----------------------------------------------------------------
                // required by DatabaseMetaData.getVersionColumns result set
                // ----------------------------------------------------------------
                addColumn(t, "SCOPE", SqlType.SQL_INTEGER);
                addColumn(t, "COLUMN_NAME", SQL_IDENTIFIER);         // not null
                addColumn(t, "DATA_TYPE", SqlType.SQL_SMALLINT);        // not null
                addColumn(t, "TYPE_NAME", SQL_IDENTIFIER);           // not null
                addColumn(t, "COLUMN_SIZE", SqlType.SQL_SMALLINT);
                addColumn(t, "BUFFER_LENGTH", SqlType.SQL_INTEGER);
                addColumn(t, "DECIMAL_DIGITS", SqlType.SQL_SMALLINT);
                addColumn(t, "PSEUDO_COLUMN", SqlType.SQL_SMALLINT);    // not null

                // -----------------------------------------------------------------
                // required by DatabaseMetaData.getVersionColumns filter parameters
                // -----------------------------------------------------------------
                addColumn(t, "TABLE_CAT", SQL_IDENTIFIER);
                addColumn(t, "TABLE_SCHEM", SQL_IDENTIFIER);
                addColumn(t, "TABLE_NAME", SQL_IDENTIFIER);          // not null

                // -----------------------------------------------------------------
                QNameManager.QName name = QNameManager.newInfoSchemaObjectName(
                    sysTableHsqlNames[ID_SYSTEM_VERSIONCOLUMNS].name, false,
                    SchemaObjectTypes.INDEX);

                t.createPrimaryKey(name, null, false);

                return t;
            }

            return t;
        }

        //------------------------------------------------------------------------------
        // SQL SCHEMATA VIEWS

        /**
         * Returns roles that are grantable by an admin user, which means all the
         * roles
         *
         * @return Table
         */
        Table ADMINISTRABLE_ROLE_AUTHORIZATIONS()
        {

            Table t = sysTables[ID_ADMINISTRABLE_ROLE_AUTHORIZATIONS];

            if (t == null)
            {
                t = createBlankTable(
                    sysTableHsqlNames[ID_ADMINISTRABLE_ROLE_AUTHORIZATIONS]);

                addColumn(t, "GRANTEE", SQL_IDENTIFIER);
                addColumn(t, "ROLE_NAME", SQL_IDENTIFIER);
                addColumn(t, "IS_GRANTABLE", SQL_IDENTIFIER);

                QNameManager.QName name = QNameManager.newInfoSchemaObjectName(
                    sysTableHsqlNames[ID_ADMINISTRABLE_ROLE_AUTHORIZATIONS].name,
                    false, SchemaObjectTypes.INDEX);

                t.createPrimaryKey(name, new int[] {
                0, 1, 2
            }, false);

                return t;
            }

            if (session.isAdmin())
            {
                insertRoles(t, session.getGrantee(), true);
            }

            return t;
        }

        /**
         * APPLICABLE_ROLES<p>
         *
         * <b>Function</b><p>
         *
         * Identifies the applicable roles for the current user.<p>
         *
         * <b>Definition</b><p>
         *
         * <pre class="SqlCodeExample">
         * CREATE RECURSIVE VIEW APPLICABLE_ROLES ( GRANTEE, ROLE_NAME, IS_GRANTABLE ) AS
         *      ( ( SELECT GRANTEE, ROLE_NAME, IS_GRANTABLE
         *            FROM DEFINITION_SCHEMA.ROLE_AUTHORIZATION_DESCRIPTORS
         *           WHERE ( GRANTEE IN ( CURRENT_USER, 'PUBLIC' )
         *                OR GRANTEE IN ( SELECT ROLE_NAME
         *                                  FROM ENABLED_ROLES ) ) )
         *      UNION
         *      ( SELECT RAD.GRANTEE, RAD.ROLE_NAME, RAD.IS_GRANTABLE
         *          FROM DEFINITION_SCHEMA.ROLE_AUTHORIZATION_DESCRIPTORS RAD
         *          JOIN APPLICABLE_ROLES R
         *            ON RAD.GRANTEE = R.ROLE_NAME ) );
         *
         * GRANT SELECT ON TABLE APPLICABLE_ROLES
         *    TO PUBLIC WITH GRANT OPTION;
         * </pre>
         */
        Table APPLICABLE_ROLES()
        {

            Table t = sysTables[ID_APPLICABLE_ROLES];

            if (t == null)
            {
                t = createBlankTable(sysTableHsqlNames[ID_APPLICABLE_ROLES]);

                addColumn(t, "GRANTEE", SQL_IDENTIFIER);
                addColumn(t, "ROLE_NAME", SQL_IDENTIFIER);
                addColumn(t, "IS_GRANTABLE", SQL_IDENTIFIER);

                QNameManager.QName name = QNameManager.newInfoSchemaObjectName(
                    sysTableHsqlNames[ID_APPLICABLE_ROLES].name, false,
                    SchemaObjectTypes.INDEX);

                t.createPrimaryKey(name, new int[] {
                0, 1, 2
            }, false);

                return t;
            }

            insertRoles(t, session.getGrantee(), session.isAdmin());

            return t;
        }

        private void insertRoles(Table t, Grantee role, bool isGrantable)
        {

            int grantee = 0;
            int role_name = 1;
            int is_grantable = 2;
            PersistentStore store = database.persistentStoreCollection.getStore(t);

            if (isGrantable)
            {
                Set roles = database.getGranteeManager().getRoleNames();
                Iterator it = roles.iterator();

                while (it.hasNext())
                {
                    String roleName = (String)it.next();
                    Object[] row = t.getEmptyRowData();

                    row[grantee] = role.getOriginalNameString();
                    row[role_name] = roleName;
                    row[is_grantable] = "YES";

                    t.insertSys(store, row);
                }
            }
            else
            {
                OrderedHashSet roles = role.getDirectRoles();

                for (int i = 0; i < roles.size(); i++)
                {
                    String roleName = (String)roles.get(i);
                    Object[] row = t.getEmptyRowData();

                    row[grantee] = role.getNameString();
                    row[role_name] = roleName;
                    row[is_grantable] = Tokens.T_NO;

                    t.insertSys(store, row);

                    role = database.getGranteeManager().getRole(roleName);

                    insertRoles(t, role, isGrantable);
                }
            }
        }

        Table ASSERTIONS()
        {

            Table t = sysTables[ID_ASSERTIONS];

            if (t == null)
            {
                t = createBlankTable(sysTableHsqlNames[ID_ASSERTIONS]);

                addColumn(t, "CONSTRAINT_CATALOG", SQL_IDENTIFIER);
                addColumn(t, "CONSTRAINT_SCHEMA", SQL_IDENTIFIER);
                addColumn(t, "CONSTRAINT_NAME", SQL_IDENTIFIER);    // not null
                addColumn(t, "IS_DEFERRABLE", YES_OR_NO);
                addColumn(t, "INITIALLY_DEFERRED", YES_OR_NO);

                QNameManager.QName name = QNameManager.newInfoSchemaObjectName(
                    sysTableHsqlNames[ID_ASSERTIONS].name, false, SchemaObjectTypes.INDEX);

                t.createPrimaryKey(name, new int[] {
                0, 1, 2
            }, false);

                return t;
            }

            //int constraint_catalog = 0;
            //int constraint_schema = 1;
            //int constraint_name = 2;
            //int is_deferrable = 3;
            //int initially_deferred = 4;

            return t;
        }

        /**
         *  SYSTEM_AUTHORIZATIONS<p>
         *
         *  <b>Function</b><p>
         *
         *  The AUTHORIZATIONS table has one row for each &lt;role name&gt; and
         *  one row for each &lt;authorization identifier &gt; referenced in the
         *  Information Schema. These are the &lt;role name&gt;s and
         *  &lt;authorization identifier&gt;s that may grant privileges as well as
         *  those that may create a schema, or currently own a schema created
         *  through a &lt;schema definition&gt;. <p>
         *
         *  <b>Definition</b><p>
         *
         *  <pre class="SqlCodeExample">
         *  CREATE TABLE AUTHORIZATIONS (
         *       AUTHORIZATION_NAME INFORMATION_SCHEMA.SQL_IDENTIFIER,
         *       AUTHORIZATION_TYPE INFORMATION_SCHEMA.CHARACTER_DATA
         *           CONSTRAINT AUTHORIZATIONS_AUTHORIZATION_TYPE_NOT_NULL
         *               NOT NULL
         *           CONSTRAINT AUTHORIZATIONS_AUTHORIZATION_TYPE_CHECK
         *               CHECK ( AUTHORIZATION_TYPE IN ( 'USER', 'ROLE' ) ),
         *           CONSTRAINT AUTHORIZATIONS_PRIMARY_KEY
         *               PRIMARY KEY (AUTHORIZATION_NAME)
         *       )
         *  </pre>
         *
         *  <b>Description</b><p>
         *
         *  <ol>
         *  <li> The values of AUTHORIZATION_TYPE have the following meanings:<p>
         *
         *  <table border cellpadding="3">
         *       <tr>
         *           <td nowrap>USER</td>
         *           <td nowrap>The value of AUTHORIZATION_NAME is a known
         *                      &lt;user identifier&gt;.</td>
         *       <tr>
         *       <tr>
         *           <td nowrap>NO</td>
         *           <td nowrap>The value of AUTHORIZATION_NAME is a &lt;role
         *                      name&gt; defined by a &lt;role definition&gt;.</td>
         *       <tr>
         *  </table> <p>
         *  </ol>
         *
         * @return Table
         */
        Table AUTHORIZATIONS()
        {

            Table t = sysTables[ID_AUTHORIZATIONS];

            if (t == null)
            {
                t = createBlankTable(sysTableHsqlNames[ID_AUTHORIZATIONS]);

                addColumn(t, "AUTHORIZATION_NAME", SQL_IDENTIFIER);    // not null
                addColumn(t, "AUTHORIZATION_TYPE", SQL_IDENTIFIER);    // not null

                // true PK
                QNameManager.QName name = QNameManager.newInfoSchemaObjectName(
                    sysTableHsqlNames[ID_AUTHORIZATIONS].name, false,
                    SchemaObjectTypes.INDEX);

                t.createPrimaryKey(name, new int[] { 0 }, true);

                return t;
            }

            PersistentStore store = database.persistentStoreCollection.getStore(t);

            // Intermediate holders
            Iterator grantees;
            Grantee grantee;
            Object[] row;

            // initialization
            grantees = session.getGrantee().visibleGrantees().iterator();

            // Do it.
            while (grantees.hasNext())
            {
                grantee = (Grantee)grantees.next();
                row = t.getEmptyRowData();
                row[0] = grantee.getOriginalNameString();
                row[1] = grantee.isRole() ? "ROLE"
                                           : "USER";

                t.insertSys(store, row);
            }

            return t;
        }

        Table CHARACTER_SETS()
        {

            Table t = sysTables[ID_CHARACTER_SETS];

            if (t == null)
            {
                t = createBlankTable(sysTableHsqlNames[ID_CHARACTER_SETS]);

                addColumn(t, "CHARACTER_SET_CATALOG", SQL_IDENTIFIER);
                addColumn(t, "CHARACTER_SET_SCHEMA", SQL_IDENTIFIER);
                addColumn(t, "CHARACTER_SET_NAME", SQL_IDENTIFIER);
                addColumn(t, "CHARACTER_REPERTOIRE", SQL_IDENTIFIER);
                addColumn(t, "FORM_OF_USE", SQL_IDENTIFIER);
                addColumn(t, "DEFAULT_COLLATE_CATALOG", SQL_IDENTIFIER);
                addColumn(t, "DEFAULT_COLLATE_SCHEMA", SQL_IDENTIFIER);
                addColumn(t, "DEFAULT_COLLATE_NAME", SQL_IDENTIFIER);

                QNameManager.QName name = QNameManager.newInfoSchemaObjectName(
                    sysTableHsqlNames[ID_CHARACTER_SETS].name, false,
                    SchemaObjectTypes.INDEX);

                t.createPrimaryKey(name, new int[] {
                0, 1, 2
            }, false);

                return t;
            }

            int character_set_catalog = 0;
            int character_set_schema = 1;
            int character_set_name = 2;
            int character_repertoire = 3;
            int form_of_use = 4;
            int default_collate_catalog = 5;
            int default_collate_schema = 6;
            int default_collate_name = 7;

            //
            PersistentStore store = database.persistentStoreCollection.getStore(t);
            Iterator it = database.schemaManager.databaseObjectIterator(
                SchemaObjectTypes.CHARSET);

            while (it.hasNext())
            {
                Charset charset = (Charset)it.next();

                if (!session.getGrantee().isAccessible(charset))
                {
                    continue;
                }

                Object[] data = t.getEmptyRowData();

                data[character_set_catalog] = database.getCatalogName().originalName;
                data[character_set_schema] = charset.getSchemaName().originalName;
                data[character_set_name] = charset.getName().originalName;
                data[character_repertoire] = "UCS";
                data[form_of_use] = "UTF16";
                data[default_collate_catalog] = data[character_set_catalog];

                if (charset._base == null)
                {
                    data[default_collate_schema] = data[character_set_schema];
                    data[default_collate_name] = data[character_set_name];
                }
                else
                {
                    data[default_collate_schema] = charset._base.schema.originalName;
                    data[default_collate_name] = charset._base.originalName;
                }

                t.insertSys(store, data);
            }

            return t;
        }

        /**
         * The CHECK_CONSTRAINT_ROUTINE_USAGE view has one row for each
         * SQL-invoked routine identified as the subject routine of either a
         * &lt;routine invocation&gt;, a &lt;method reference&gt;, a
         * &lt;method invocation&gt;, or a &lt;static method invocation&gt;
         * contained in an &lt;assertion definition&gt;, a &lt;domain
         * constraint&gt;, or a &lt;table constraint definition&gt;. <p>
         *
         * <b>Definition:</b> <p>
         *
         * <pre class="SqlCodeExample">
         * CREATE TABLE SYSTEM_CHECK_ROUTINE_USAGE (
         *      CONSTRAINT_CATALOG      VARCHAR NULL,
         *      CONSTRAINT_SCHEMA       VARCHAR NULL,
         *      CONSTRAINT_NAME         VARCHAR NOT NULL,
         *      SPECIFIC_CATALOG        VARCHAR NULL,
         *      SPECIFIC_SCHEMA         VARCHAR NULL,
         *      SPECIFIC_NAME           VARCHAR NOT NULL,
         *      UNIQUE( CONSTRAINT_CATALOG, CONSTRAINT_SCHEMA, CONSTRAINT_NAME,
         *              SPECIFIC_CATALOG, SPECIFIC_SCHEMA, SPECIFIC_NAME )
         * )
         * </pre>
         *
         * <b>Description:</b> <p>
         *
         * <ol>
         * <li> The CHECK_ROUTINE_USAGE table has one row for each
         *      SQL-invoked routine R identified as the subject routine of either a
         *      &lt;routine invocation&gt;, a &lt;method reference&gt;, a &lt;method
         *      invocation&gt;, or a &lt;static method invocation&gt; contained in
         *      an &lt;assertion definition&gt; or in the &lt;check constraint
         *      definition&gt; contained in either a &lt;domain constraint&gt; or a
         *      &lt;table constraint definition&gt;. <p>
         *
         * <li> The values of CONSTRAINT_CATALOG, CONSTRAINT_SCHEMA, and
         *      CONSTRAINT_NAME are the catalog name, unqualified schema name, and
         *      qualified identifier, respectively, of the assertion or check
         *     constraint being described. <p>
         *
         * <li> The values of SPECIFIC_CATALOG, SPECIFIC_SCHEMA, and SPECIFIC_NAME
         *      are the catalog name, unqualified schema name, and qualified
         *      identifier, respectively, of the specific name of R. <p>
         *
         * </ol>
         *
         * @return Table
         */
        Table CHECK_CONSTRAINT_ROUTINE_USAGE()
        {

            Table t = sysTables[ID_CHECK_CONSTRAINT_ROUTINE_USAGE];

            if (t == null)
            {
                t = createBlankTable(
                    sysTableHsqlNames[ID_CHECK_CONSTRAINT_ROUTINE_USAGE]);

                addColumn(t, "CONSTRAINT_CATALOG", SQL_IDENTIFIER);
                addColumn(t, "CONSTRAINT_SCHEMA", SQL_IDENTIFIER);
                addColumn(t, "CONSTRAINT_NAME", SQL_IDENTIFIER);    // not null
                addColumn(t, "SPECIFIC_CATALOG", SQL_IDENTIFIER);
                addColumn(t, "SPECIFIC_SCHEMA", SQL_IDENTIFIER);
                addColumn(t, "SPECIFIC_NAME", SQL_IDENTIFIER);      // not null

                QNameManager.QName name = QNameManager.newInfoSchemaObjectName(
                    sysTableHsqlNames[ID_CHECK_CONSTRAINT_ROUTINE_USAGE].name, false,
                    SchemaObjectTypes.INDEX);

                t.createPrimaryKey(name, new int[] {
                0, 1, 2, 3, 4, 5
            }, false);

                return t;
            }

            // column number mappings
            int constraint_catalog = 0;
            int constraint_schema = 1;
            int constraint_name = 2;
            int specific_catalog = 3;
            int specific_schema = 4;
            int specific_name = 5;

            //
            PersistentStore store = database.persistentStoreCollection.getStore(t);

            // Intermediate holders
            Iterator constraints;
            Constraint constraint;
            OrderedHashSet references;
            //RoutineSchema routine;
            Object[] row;

            constraints = database.schemaManager.databaseObjectIterator(
                SchemaObjectTypes.CONSTRAINT);

            while (constraints.hasNext())
            {
                QNameManager.QName constraintName = (QNameManager.QName)constraints.next();
                Table table;

                if (constraintName.parent == null)
                {
                    continue;
                }

                try
                {
                    table = (Table)database.schemaManager.getSchemaObject(
                        constraintName.parent.originalName,
                        constraintName.parent.schema.originalName, SchemaObjectTypes.TABLE);
                }
                catch (Exception)
                {
                    continue;
                }

                constraint = table.getConstraint(constraintName.originalName);

                if (constraint.getConstraintType()
                        != SchemaObjectConstraintTypes.CHECK)
                {
                    continue;
                }

                references = constraint.getReferences();

                for (int i = 0; i < references.size(); i++)
                {
                    QNameManager.QName name = (QNameManager.QName)references.get(i);

                    if (name.type != SchemaObjectTypes.SPECIFIC_ROUTINE)
                    {
                        continue;
                    }

                    row = t.getEmptyRowData();
                    row[constraint_catalog] = database.getCatalogName().originalName;
                    row[constraint_schema] = constraint.getSchemaName().originalName;
                    row[constraint_name] = constraint.getName().originalName;
                    row[specific_catalog] = database.getCatalogName().originalName;
                    row[specific_schema] = name.schema.originalName;
                    row[specific_name] = name.originalName;

                    t.insertSys(store, row);
                }
            }

            return t;
        }

        /**
         * The CHECK_CONSTRAINTS view has one row for each domain
         * constraint, table check constraint, and assertion. <p>
         *
         * <b>Definition:</b><p>
         *
         * <pre class="SqlCodeExample">
         *      CONSTRAINT_CATALOG  VARCHAR NULL,
         *      CONSTRAINT_SCHEMA   VARCHAR NULL,
         *      CONSTRAINT_NAME     VARCHAR NOT NULL,
         *      CHECK_CLAUSE        VARCHAR NOT NULL,
         * </pre>
         *
         * <b>Description:</b><p>
         *
         * <ol>
         * <li> A constraint is shown in this view if the authorization for the
         *      schema that contains the constraint is the current user or is a role
         *      assigned to the current user. <p>
         *
         * <li> The values of CONSTRAINT_CATALOG, CONSTRAINT_SCHEMA and
         *      CONSTRAINT_NAME are the catalog name, unqualified schema name,
         *      and qualified identifier, respectively, of the constraint being
         *      described. <p>
         *
         * <li> Case: <p>
         *
         *      <table>
         *          <tr>
         *               <td valign="top" halign="left">a)</td>
         *               <td> If the character representation of the
         *                    &lt;search condition&gt; contained in the
         *                    &lt;check constraint definition&gt;,
         *                    &lt;domain constraint definition&gt;, or
         *                    &lt;assertion definition&gt; that defined
         *                    the check constraint being described can be
         *                    represented without truncation, then the
         *                    value of CHECK_CLAUSE is that character
         *                    representation. </td>
         *          </tr>
         *          <tr>
         *              <td align="top" halign="left">b)</td>
         *              <td>Otherwise, the value of CHECK_CLAUSE is the
         *                  null value.</td>
         *          </tr>
         *      </table>
         * </ol>
         *
         * @return Table
         */
        Table CHECK_CONSTRAINTS()
        {

            Table t = sysTables[ID_CHECK_CONSTRAINTS];

            if (t == null)
            {
                t = createBlankTable(sysTableHsqlNames[ID_CHECK_CONSTRAINTS]);

                addColumn(t, "CONSTRAINT_CATALOG", SQL_IDENTIFIER);
                addColumn(t, "CONSTRAINT_SCHEMA", SQL_IDENTIFIER);
                addColumn(t, "CONSTRAINT_NAME", SQL_IDENTIFIER);    // not null
                addColumn(t, "CHECK_CLAUSE", CHARACTER_DATA);       // not null

                QNameManager.QName name = QNameManager.newInfoSchemaObjectName(
                    sysTableHsqlNames[ID_CHECK_CONSTRAINTS].name, false,
                    SchemaObjectTypes.INDEX);

                t.createPrimaryKey(name, new int[] {
                2, 1, 0
            }, false);

                return t;
            }

            // column number mappings
            int constraint_catalog = 0;
            int constraint_schema = 1;
            int constraint_name = 2;
            int check_clause = 3;

            //
            PersistentStore store = database.persistentStoreCollection.getStore(t);

            // calculated column values
            // Intermediate holders
            Iterator tables;
            Table table;
            Constraint[] tableConstraints;
            int constraintCount;
            Constraint constraint;
            Object[] row;

            //
            tables =
                database.schemaManager.databaseObjectIterator(SchemaObjectTypes.TABLE);

            while (tables.hasNext())
            {
                table = (Table)tables.next();

                if (table.isView()
                        || !session.getGrantee().isFullyAccessibleByRole(
                            table.getName()))
                {
                    continue;
                }

                tableConstraints = table.getConstraints();
                constraintCount = tableConstraints.Length;

                for (int i = 0; i < constraintCount; i++)
                {
                    constraint = tableConstraints[i];

                    if (constraint.getConstraintType()
                            != SchemaObjectConstraintTypes.CHECK)
                    {
                        continue;
                    }

                    row = t.getEmptyRowData();
                    row[constraint_catalog] = database.getCatalogName().originalName;
                    row[constraint_schema] = table.getSchemaName().originalName;
                    row[constraint_name] = constraint.getName().originalName;

                    try
                    {
                        row[check_clause] = constraint.getCheckSQL();
                    }
                    catch (Exception) { }

                    t.insertSys(store, row);
                }
            }

            Iterator it =
                database.schemaManager.databaseObjectIterator(SchemaObjectTypes.DOMAIN);

            while (it.hasNext())
            {
                SqlType domain = (SqlType)it.next();

                if (!domain.isDomainType())
                {
                    continue;
                }

                if (!session.getGrantee().isFullyAccessibleByRole(
                        domain.getName()))
                {
                    continue;
                }

                tableConstraints = domain.userTypeModifier.getConstraints();
                constraintCount = tableConstraints.Length;

                for (int i = 0; i < constraintCount; i++)
                {
                    constraint = tableConstraints[i];
                    row = t.getEmptyRowData();
                    row[constraint_catalog] = database.getCatalogName().originalName;
                    row[constraint_schema] = domain.getSchemaName().originalName;
                    row[constraint_name] = constraint.getName().originalName;

                    try
                    {
                        row[check_clause] = constraint.getCheckSQL();
                    }
                    catch (Exception) { }

                    t.insertSys(store, row);
                }
            }

            return t;
        }

        /**
         * COLLATIONS<p>
         *
         * <b>Function<b><p>
         *
         * The COLLATIONS view has one row for each character collation
         * descriptor. <p>
         *
         * <b>Definition</b>
         *
         * <pre class="SqlCodeExample">
         * CREATE TABLE COLLATIONS (
         *      COLLATION_CATALOG INFORMATION_SCHEMA.SQL_IDENTIFIER,
         *      COLLATION_SCHEMA INFORMATION_SCHEMA.SQL_IDENTIFIER,
         *      COLLATION_NAME INFORMATION_SCHEMA.SQL_IDENTIFIER,
         *      PAD_ATTRIBUTE INFORMATION_SCHEMA.CHARACTER_DATA
         *          CONSTRAINT COLLATIONS_PAD_ATTRIBUTE_CHECK
         *              CHECK ( PAD_ATTRIBUTE IN
         *                  ( 'NO PAD', 'PAD SPACE' ) )
         * )
         * </pre>
         *
         * <b>Description</b><p>
         *
         * <ol>
         *      <li>The values of COLLATION_CATALOG, COLLATION_SCHEMA, and
         *          COLLATION_NAME are the catalog name, unqualified schema name,
         *          and qualified identifier, respectively, of the collation being
         *          described.<p>
         *
         *      <li>The values of PAD_ATTRIBUTE have the following meanings:<p>
         *
         *      <table border cellpadding="3">
         *          <tr>
         *              <td nowrap>NO PAD</td>
         *              <td nowrap>The collation being described has the NO PAD
         *                  characteristic.</td>
         *          <tr>
         *          <tr>
         *              <td nowrap>PAD</td>
         *              <td nowrap>The collation being described has the PAD SPACE
         *                         characteristic.</td>
         *          <tr>
         *      </table> <p>
         * </ol>
         *
         * @return Table
         */
        Table COLLATIONS()
        {

            Table t = sysTables[ID_COLLATIONS];

            if (t == null)
            {
                t = createBlankTable(sysTableHsqlNames[ID_COLLATIONS]);

                addColumn(t, "COLLATION_CATALOG", SQL_IDENTIFIER);
                addColumn(t, "COLLATION_SCHEMA", SQL_IDENTIFIER);    // not null
                addColumn(t, "COLLATION_NAME", SQL_IDENTIFIER);      // not null
                addColumn(t, "PAD_ATTRIBUTE", CHARACTER_DATA);

                // false PK, as rows may have NULL COLLATION_CATALOG
                QNameManager.QName name = QNameManager.newInfoSchemaObjectName(
                    sysTableHsqlNames[ID_COLLATIONS].name, false, SchemaObjectTypes.INDEX);

                t.createPrimaryKey(name, new int[] {
                0, 1, 2
            }, false);

                return t;
            }

            // Column number mappings
            int collation_catalog = 0;
            int collation_schema = 1;
            int collation_name = 2;
            int pad_attribute = 3;

            //
            PersistentStore store = database.persistentStoreCollection.getStore(t);

            // Intermediate holders    
            String collationSchema = SqlInvariants.PUBLIC_SCHEMA;
            String padAttribute = "NO PAD";
            Object[] row;

            // Initialization


            // Do it.
            foreach (var collation in Collation.nameToCSharpName.Keys)
            {
                row = t.getEmptyRowData();
                row[collation_catalog] = database.getCatalogName().originalName;
                row[collation_schema] = collationSchema;
                row[collation_name] = collation;
                row[pad_attribute] = padAttribute;

                t.insertSys(store, row);
            }

            return t;
        }

        /**
         * For generated columns
         * <p>
         *
         * @return Table
         */
        Table COLUMN_COLUMN_USAGE()
        {

            Table t = sysTables[ID_COLUMN_COLUMN_USAGE];

            if (t == null)
            {
                t = createBlankTable(sysTableHsqlNames[ID_COLUMN_COLUMN_USAGE]);

                addColumn(t, "TABLE_CATALOG", SQL_IDENTIFIER);
                addColumn(t, "TABLE_SCHEMA", SQL_IDENTIFIER);
                addColumn(t, "TABLE_NAME", SQL_IDENTIFIER);
                addColumn(t, "COLUMN_NAME", SQL_IDENTIFIER);
                addColumn(t, "DEPENDENT_COLUMN", SQL_IDENTIFIER);

                QNameManager.QName name = QNameManager.newInfoSchemaObjectName(
                    sysTableHsqlNames[ID_COLUMN_COLUMN_USAGE].name, false,
                    SchemaObjectTypes.INDEX);

                t.createPrimaryKey(name, new int[] {
                0, 1, 2, 3, 4
            }, false);

                return t;
            }

            //int table_catalog = 0;
            //int table_schema = 1;
            //int table_name = 2;
            //int column_name = 3;
            //int dependent_column = 4;

            return t;
        }

        /**
         * Domains are shown if the authorization is the user or a role given to the
         * user.
         *
         * <p>
         *
         * @return Table
         */
        Table COLUMN_DOMAIN_USAGE()
        {

            Table t = sysTables[ID_COLUMN_DOMAIN_USAGE];

            if (t == null)
            {
                t = createBlankTable(sysTableHsqlNames[ID_COLUMN_DOMAIN_USAGE]);

                addColumn(t, "DOMAIN_CATALOG", SQL_IDENTIFIER);
                addColumn(t, "DOMAIN_SCHEMA", SQL_IDENTIFIER);
                addColumn(t, "DOMAIN_NAME", SQL_IDENTIFIER);
                addColumn(t, "TABLE_CATALOG", SQL_IDENTIFIER);
                addColumn(t, "TABLE_SCHEMA", SQL_IDENTIFIER);
                addColumn(t, "TABLE_NAME", SQL_IDENTIFIER);     // not null
                addColumn(t, "COLUMN_NAME", SQL_IDENTIFIER);    // not null

                QNameManager.QName name = QNameManager.newInfoSchemaObjectName(
                    sysTableHsqlNames[ID_COLUMN_DOMAIN_USAGE].name, false,
                    SchemaObjectTypes.INDEX);

                t.createPrimaryKey(name, new int[] {
                0, 1, 2, 3, 4, 5, 6
            }, false);

                return t;
            }

            PersistentStore store = database.persistentStoreCollection.getStore(t);
            Session sys = database.sessionManager.newSysSession(
                SqlInvariants.INFORMATION_SCHEMA_QNAME, session.getUser());
            Result rs = sys.executeDirectStatement(
                "SELECT DOMAIN_CATALOG, DOMAIN_SCHEMA, DOMAIN_NAME, TABLE_CATALOG, "
                + "TABLE_SCHEMA, TABLE_NAME, COLUMN_NAME FROM INFORMATION_SCHEMA.COLUMNS "
                + "WHERE DOMAIN_NAME IS NOT NULL;");

            t.insertSys(store, rs);
            sys.close();

            return t;
        }

        /**
         * UDT's are shown if the authorization is the user or a role given to the
         * user.
         *
         * <p>
         *
         * @return Table
         */
        Table COLUMN_UDT_USAGE()
        {

            Table t = sysTables[ID_COLUMN_UDT_USAGE];

            if (t == null)
            {
                t = createBlankTable(sysTableHsqlNames[ID_COLUMN_UDT_USAGE]);

                addColumn(t, "UDT_CATALOG", SQL_IDENTIFIER);
                addColumn(t, "UDT_SCHEMA", SQL_IDENTIFIER);
                addColumn(t, "UDT_NAME", SQL_IDENTIFIER);
                addColumn(t, "TABLE_CATALOG", SQL_IDENTIFIER);
                addColumn(t, "TABLE_SCHEMA", SQL_IDENTIFIER);
                addColumn(t, "TABLE_NAME", SQL_IDENTIFIER);     // not null
                addColumn(t, "COLUMN_NAME", SQL_IDENTIFIER);    // not null

                QNameManager.QName name = QNameManager.newInfoSchemaObjectName(
                    sysTableHsqlNames[ID_COLUMN_UDT_USAGE].name, false,
                    SchemaObjectTypes.INDEX);

                t.createPrimaryKey(name, new int[] {
                0, 1, 2, 3, 4, 5, 6
            }, false);

                return t;
            }

            PersistentStore store = database.persistentStoreCollection.getStore(t);
            Session sys = database.sessionManager.newSysSession(
                SqlInvariants.INFORMATION_SCHEMA_QNAME, session.getUser());
            Result rs = sys.executeDirectStatement(
                "SELECT UDT_CATALOG, UDT_SCHEMA, UDT_NAME, TABLE_CATALOG, "
                + "TABLE_SCHEMA, TABLE_NAME, COLUMN_NAME FROM INFORMATION_SCHEMA.COLUMNS "
                + "WHERE UDT_NAME IS NOT NULL;");

            t.insertSys(store, rs);
            sys.close();

            return t;
        }

        Table COLUMNS()
        {

            Table t = sysTables[ID_COLUMNS];

            if (t == null)
            {
                t = createBlankTable(sysTableHsqlNames[ID_COLUMNS]);

                addColumn(t, "TABLE_CATALOG", SQL_IDENTIFIER);           //0
                addColumn(t, "TABLE_SCHEMA", SQL_IDENTIFIER);
                addColumn(t, "TABLE_NAME", SQL_IDENTIFIER);
                addColumn(t, "COLUMN_NAME", SQL_IDENTIFIER);
                addColumn(t, "ORDINAL_POSITION", CARDINAL_NUMBER);
                addColumn(t, "COLUMN_DEFAULT", CHARACTER_DATA);
                addColumn(t, "IS_NULLABLE", YES_OR_NO);
                addColumn(t, "DATA_TYPE", CHARACTER_DATA);
                addColumn(t, "CHARACTER_MAXIMUM_LENGTH", CARDINAL_NUMBER);
                addColumn(t, "CHARACTER_OCTET_LENGTH", CARDINAL_NUMBER);
                addColumn(t, "NUMERIC_PRECISION", CARDINAL_NUMBER);      //10
                addColumn(t, "NUMERIC_PRECISION_RADIX", CARDINAL_NUMBER);
                addColumn(t, "NUMERIC_SCALE", CARDINAL_NUMBER);
                addColumn(t, "DATETIME_PRECISION", CARDINAL_NUMBER);
                addColumn(t, "INTERVAL_TYPE", CHARACTER_DATA);
                addColumn(t, "INTERVAL_PRECISION", CARDINAL_NUMBER);
                addColumn(t, "CHARACTER_SET_CATALOG", CHARACTER_DATA);
                addColumn(t, "CHARACTER_SET_SCHEMA", SQL_IDENTIFIER);
                addColumn(t, "CHARACTER_SET_NAME", SQL_IDENTIFIER);
                addColumn(t, "COLLATION_CATALOG", SQL_IDENTIFIER);
                addColumn(t, "COLLATION_SCHEMA", SQL_IDENTIFIER);        //20
                addColumn(t, "COLLATION_NAME", SQL_IDENTIFIER);
                addColumn(t, "DOMAIN_CATALOG", SQL_IDENTIFIER);
                addColumn(t, "DOMAIN_SCHEMA", SQL_IDENTIFIER);
                addColumn(t, "DOMAIN_NAME", SQL_IDENTIFIER);
                addColumn(t, "UDT_CATALOG", SQL_IDENTIFIER);
                addColumn(t, "UDT_SCHEMA", SQL_IDENTIFIER);
                addColumn(t, "UDT_NAME", SQL_IDENTIFIER);
                addColumn(t, "SCOPE_CATALOG", SQL_IDENTIFIER);
                addColumn(t, "SCOPE_SCHEMA", SQL_IDENTIFIER);
                addColumn(t, "SCOPE_NAME", SQL_IDENTIFIER);              //30
                addColumn(t, "MAXIMUM_CARDINALITY", CARDINAL_NUMBER);    // NULL (only for array tyes)
                addColumn(t, "DTD_IDENTIFIER", SQL_IDENTIFIER);
                addColumn(t, "IS_SELF_REFERENCING", YES_OR_NO);
                addColumn(t, "IS_IDENTITY", YES_OR_NO);
                addColumn(t, "IDENTITY_GENERATION", CHARACTER_DATA);     // ALLWAYS / BY DEFAULT
                addColumn(t, "IDENTITY_START", CHARACTER_DATA);
                addColumn(t, "IDENTITY_INCREMENT", CHARACTER_DATA);
                addColumn(t, "IDENTITY_MAXIMUM", CHARACTER_DATA);
                addColumn(t, "IDENTITY_MINIMUM", CHARACTER_DATA);
                addColumn(t, "IDENTITY_CYCLE", YES_OR_NO);               //40
                addColumn(t, "IS_GENERATED", CHARACTER_DATA);            // ALLWAYS / NEVER
                addColumn(t, "GENERATION_EXPRESSION", CHARACTER_DATA);
                addColumn(t, "IS_UPDATABLE", YES_OR_NO);
                addColumn(t, "DECLARED_DATA_TYPE", CHARACTER_DATA);
                addColumn(t, "DECLARED_NUMERIC_PRECISION", CARDINAL_NUMBER);
                addColumn(t, "DECLARED_NUMERIC_SCALE", CARDINAL_NUMBER);

                // order: TABLE_SCHEM, TABLE_NAME, ORDINAL_POSITION
                // added for unique: TABLE_CAT
                // false PK, as TABLE_SCHEM and/or TABLE_CAT may be null
                QNameManager.QName name = QNameManager.newInfoSchemaObjectName(
                    sysTableHsqlNames[ID_COLUMNS].name, false, SchemaObjectTypes.INDEX);

                t.createPrimaryKey(name, new int[] {
                3, 2, 1, 4
            }, false);

                return t;
            }

            // column number mappings
            int table_cat = 0;
            int table_schem = 1;
            int table_name = 2;
            int column_name = 3;
            int ordinal_position = 4;
            int column_default = 5;
            int is_nullable = 6;
            int data_type = 7;
            int character_maximum_length = 8;
            int character_octet_length = 9;
            int numeric_precision = 10;
            int numeric_precision_radix = 11;
            int numeric_scale = 12;
            int datetime_precision = 13;
            int interval_type = 14;
            int interval_precision = 15;
            int character_set_catalog = 16;
            int character_set_schema = 17;
            int character_set_name = 18;
            int collation_catalog = 19;
            int collation_schema = 20;
            int collation_name = 21;
            int domain_catalog = 22;
            int domain_schema = 23;
            int domain_name = 24;
            int udt_catalog = 25;
            int udt_schema = 26;
            int udt_name = 27;
            int scope_catalog = 28;
            int scope_schema = 29;
            int scope_name = 30;
            int maximum_cardinality = 31;
            int dtd_identifier = 32;
            int is_self_referencing = 33;
            int is_identity = 34;
            int identity_generation = 35;
            int identity_start = 36;
            int identity_increment = 37;
            int identity_maximum = 38;
            int identity_minimum = 39;
            int identity_cycle = 40;
            int is_generated = 41;
            int generation_expression = 42;
            int is_updatable = 43;
            int declared_data_type = 44;
            int declared_numeric_precision = 45;
            int declared_numeric_scale = 46;

            //
            PersistentStore store = database.persistentStoreCollection.getStore(t);

            // intermediate holders
            int columnCount;
            Iterator tables;
            Table table;
            Object[] row;
            OrderedHashSet columnList;
            SqlType type;

            // Initialization
            tables = allTables();

            while (tables.hasNext())
            {
                table = (Table)tables.next();
                columnList =
                    session.getGrantee().getColumnsForAllPrivileges(table);

                if (columnList.isEmpty())
                {
                    continue;
                }

                columnCount = table.getColumnCount();

                for (int i = 0; i < columnCount; i++)
                {
                    ColumnSchema column = table.getColumn(i);

                    type = column.getDataType();

                    if (!columnList.contains(column.getName()))
                    {
                        continue;
                    }

                    row = t.getEmptyRowData();
                    row[table_cat] = database.getCatalogName().originalName;
                    row[table_schem] = table.getSchemaName().originalName;
                    row[table_name] = table.getName().originalName;
                    row[column_name] = column.getName().originalName;
                    row[ordinal_position] = (i + 1);
                    row[column_default] = column.getDefaultSQL();
                    row[is_nullable] = column.isNullable() ? "YES"
                                                                : "NO";
                    row[data_type] = type.getFullNameString();

                    // common type block
                    if (type.isCharacterType())
                    {
                        row[character_maximum_length] =
                            (long)(type.precision);
                        row[character_octet_length] =
                            (long)(type.precision * 2);
                        row[character_set_catalog] =
                            database.getCatalogName().originalName;
                        row[character_set_schema] =
                            ((CharacterType)type).getCharacterSet()
                                .getSchemaName().originalName;
                        row[character_set_name] =
                            ((CharacterType)type).getCharacterSet().getName()
                                .originalName;
                        row[collation_catalog] = database.getCatalogName().originalName;
                        row[collation_schema] =
                            ((CharacterType)type).getCollation().getSchemaName()
                                .originalName;
                        row[collation_name] =
                            ((CharacterType)type).getCollation().getName().originalName;
                    }
                    else if (type.isNumberType())
                    {
                        row[numeric_precision] = (long)(
                            ((NumberType)type).getNumericPrecisionInRadix());
                        row[declared_numeric_precision] = (long)(
                            ((NumberType)type).getNumericPrecisionInRadix());

                        if (type.isExactNumberType())
                        {
                            row[numeric_scale] = row[declared_numeric_scale] =
                                (long)(type.scale);
                        }

                        row[numeric_precision_radix] =
                            (long)(type.getPrecisionRadix());
                    }
                    else if (type.isBooleanType()) { }
                    else if (type.isDateTimeType())
                    {
                        row[datetime_precision] = (long)(type.scale);
                    }
                    else if (type.isIntervalType())
                    {
                        row[data_type] = "INTERVAL";
                        row[interval_type] =
                            IntervalType.getQualifier(type.typeCode);
                        row[interval_precision] =
                            (long)(type.precision);
                        row[datetime_precision] = (long)(type.scale);
                    }
                    else if (type.isBinaryType())
                    {
                        row[character_maximum_length] =
                            (long)(type.precision);
                        row[character_octet_length] =
                            (long)(type.precision);
                    }
                    else if (type.isBitType())
                    {
                        row[character_maximum_length] =
                            (long)(type.precision);
                        row[character_octet_length] =
                            (long)(type.precision);
                    }

                    if (type.isDomainType())
                    {
                        row[domain_catalog] = database.getCatalogName().originalName;
                        row[domain_schema] = type.getSchemaName().originalName;
                        row[domain_name] = type.getName().originalName;
                    }

                    if (type.isDistinctType())
                    {
                        row[udt_catalog] = database.getCatalogName().originalName;
                        row[udt_schema] = type.getSchemaName().originalName;
                        row[udt_name] = type.getName().originalName;
                    }

                    row[scope_catalog] = null;
                    row[scope_schema] = null;
                    row[scope_name] = null;
                    row[maximum_cardinality] = null;
                    row[dtd_identifier] = null;
                    row[is_self_referencing] = null;
                    row[is_identity] = column.isIdentity() ? "YES"
                                                                   : "NO";

                    if (column.isIdentity())
                    {
                        NumberSequence sequence = column.getIdentitySequence();

                        row[identity_generation] = sequence.isAlways() ? "ALWAYS"
                                                                       : "BY DEFAULT";
                        row[identity_start] =
                            (sequence.getStartValue()).ToString();
                        row[identity_increment] =
                            (sequence.getIncrement()).ToString();
                        row[identity_maximum] =
                            (sequence.getMaxValue()).ToString();
                        row[identity_minimum] =
                            (sequence.getMinValue()).ToString();
                        row[identity_cycle] = sequence.isCycle() ? "YES"
                                                                 : "NO";
                    }

                    row[is_generated] = "NEVER";
                    row[generation_expression] = null;
                    row[is_updatable] = table.isWritable() ? "YES"
                                                                    : "NO";
                    row[declared_data_type] = row[data_type];

                    if (type.isNumberType())
                    {
                        row[declared_numeric_precision] = row[numeric_precision];
                        row[declared_numeric_scale] = row[numeric_scale];
                    }

                    t.insertSys(store, row);
                }
            }

            return t;
        }

        /**
         * The CONSTRAINT_COLUMN_USAGE view has one row for each column identified by
         * a table constraint or assertion.<p>
         *
         * <b>Definition:</b><p>
         *
         *      TABLE_CATALOG       VARCHAR
         *      TABLE_SCHEMA        VARCHAR
         *      TABLE_NAME          VARCHAR
         *      COLUMN_NAME         VARCHAR
         *      CONSTRAINT_CATALOG  VARCHAR
         *      CONSTRAINT_SCHEMA   VARCHAR
         *      CONSTRAINT_NAME     VARCHAR
         *
         * </pre>
         *
         * <b>Description:</b> <p>
         *
         * <ol>
         * <li> The values of TABLE_CATALOG, TABLE_SCHEMA, TABLE_NAME, and
         *      COLUMN_NAME are the catalog name, unqualified schema name,
         *      qualified identifier, and column name, respectively, of a column
         *      identified by a &lt;column reference&gt; explicitly or implicitly
         *      contained in the &lt;search condition&gt; of the constraint
         *      being described.
         *
         * <li> The values of CONSTRAINT_CATALOG, CONSTRAINT_SCHEMA, and
         *      CONSTRAINT_NAME are the catalog name, unqualified schema name,
         *      and qualified identifier, respectively, of the constraint being
         *      described. <p>
         *
         * </ol>
         *
         * @return Table
         */
        Table CONSTRAINT_COLUMN_USAGE()
        {

            Table t = sysTables[ID_CONSTRAINT_COLUMN_USAGE];

            if (t == null)
            {
                t = createBlankTable(sysTableHsqlNames[ID_CONSTRAINT_COLUMN_USAGE]);

                addColumn(t, "TABLE_CATALOG", SQL_IDENTIFIER);
                addColumn(t, "TABLE_SCHEMA", SQL_IDENTIFIER);
                addColumn(t, "TABLE_NAME", SQL_IDENTIFIER);         // not null
                addColumn(t, "COLUMN_NAME", SQL_IDENTIFIER);        // not null
                addColumn(t, "CONSTRAINT_CATALOG", SQL_IDENTIFIER);
                addColumn(t, "CONSTRAINT_SCHEMA", SQL_IDENTIFIER);
                addColumn(t, "CONSTRAINT_NAME", SQL_IDENTIFIER);    // not null

                QNameManager.QName name = QNameManager.newInfoSchemaObjectName(
                    sysTableHsqlNames[ID_CONSTRAINT_COLUMN_USAGE].name, false,
                    SchemaObjectTypes.INDEX);

                t.createPrimaryKey(name, new int[] {
                0, 1, 2, 3, 4, 5, 6
            }, false);

                return t;
            }

            // column number mappings
            int table_catalog = 0;
            int table_schems = 1;
            int table_name = 2;
            int column_name = 3;
            int constraint_catalog = 4;
            int constraint_schema = 5;
            int constraint_name = 6;

            //
            PersistentStore store = database.persistentStoreCollection.getStore(t);

            // calculated column values
            String constraintCatalog;
            String constraintSchema;
            String constraintName;

            // Intermediate holders
            Iterator tables;
            Table table;
            Constraint[] constraints;
            int constraintCount;
            Constraint constraint;
            Iterator iterator;
            Object[] row;

            // Initialization
            tables =
                database.schemaManager.databaseObjectIterator(SchemaObjectTypes.TABLE);

            // Do it.
            while (tables.hasNext())
            {
                table = (Table)tables.next();

                if (table.isView()
                        || !session.getGrantee().isFullyAccessibleByRole(
                            table.getName()))
                {
                    continue;
                }

                constraints = table.getConstraints();
                constraintCount = constraints.Length;
                constraintCatalog = database.getCatalogName().originalName;
                constraintSchema = table.getSchemaName().originalName;

                // process constraints
                for (int i = 0; i < constraintCount; i++)
                {
                    constraint = constraints[i];
                    constraintName = constraint.getName().originalName;

                    switch (constraint.getConstraintType())
                    {

                        case SchemaObjectConstraintTypes.CHECK:
                            {
                                OrderedHashSet expressions =
                                    constraint.getCheckColumnExpressions();

                                if (expressions == null)
                                {
                                    break;
                                }

                                iterator = expressions.iterator();

                                // calculate distinct column references
                                while (iterator.hasNext())
                                {
                                    ExpressionColumn expr =
                                        (ExpressionColumn)iterator.next();
                                    QNameManager.QName name = expr.getBaseColumnHsqlName();

                                    if (name.type != SchemaObjectTypes.COLUMN)
                                    {
                                        continue;
                                    }

                                    row = t.getEmptyRowData();
                                    row[table_catalog] =
                                        database.getCatalogName().originalName;
                                    row[table_schems] = name.schema.originalName;
                                    row[table_name] = name.parent.originalName;
                                    row[column_name] = name.originalName;
                                    row[constraint_catalog] = constraintCatalog;
                                    row[constraint_schema] = constraintSchema;
                                    row[constraint_name] = constraintName;

                                    try
                                    {
                                        t.insertSys(store, row);
                                    }
                                    catch (CoreException ) { }
                                }

                                break;
                            }
                        case SchemaObjectConstraintTypes.UNIQUE:
                        case SchemaObjectConstraintTypes.PRIMARY_KEY:
                        case SchemaObjectConstraintTypes.FOREIGN_KEY:
                            {
                                Table target = table;
                                int[] cols = constraint.getMainColumns();

                                if (constraint.getConstraintType()
                                        == SchemaObjectConstraintTypes.FOREIGN_KEY)
                                {
                                    target = constraint.getMain();
                                }

                                /*
                                                       checkme - it seems foreign key columns are not included
                                                       but columns of the referenced unique constraint are included

                                                        if (constraint.getType() == Constraint.FOREIGN_KEY) {
                                                            for (int j = 0; j < cols.Length; j++) {
                                                                row = t.getEmptyRowData();

                                                                Table mainTable = constraint.getMain();

                                                                row[table_catalog] = database.getCatalog();
                                                                row[table_schems] =
                                                                    mainTable.getSchemaName().name;
                                                                row[table_name] = mainTable.getName().name;
                                                                row[column_name] = mainTable.getColumn(
                                                                    cols[j]).columnName.name;
                                                                row[constraint_catalog] = constraintCatalog;
                                                                row[constraint_schema]  = constraintSchema;
                                                                row[constraint_name]    = constraintName;

                                                                try {
                                                                    t.insertSys(row);
                                                                } catch (CoreException e) {}
                                                            }

                                                            cols = constraint.getRefColumns();
                                                        }
                                */
                                for (int j = 0; j < cols.Length; j++)
                                {
                                    row = t.getEmptyRowData();
                                    row[table_catalog] =
                                        database.getCatalogName().originalName;
                                    row[table_schems] = constraintSchema;
                                    row[table_name] = target.getName().originalName;
                                    row[column_name] =
                                        target.getColumn(cols[j]).getName().originalName;
                                    row[constraint_catalog] = constraintCatalog;
                                    row[constraint_schema] = constraintSchema;
                                    row[constraint_name] = constraintName;

                                    try
                                    {
                                        t.insertSys(store, row);
                                    }
                                    catch (CoreException ) { }
                                }

                                //
                            }
                            break;
                    }
                }
            }

            return t;
        }

        /**
         * The CONSTRAINT_TABLE_USAGE view has one row for each table identified by a
         * &lt;table name&gt; simply contained in a &lt;table reference&gt;
         * contained in the &lt;search condition&gt; of a check constraint,
         * domain constraint, or assertion. It has one row for each table
         * containing / referenced by each PRIMARY KEY, UNIQUE and FOREIGN KEY
         * constraint<p>
         *
         * <b>Definition:</b> <p>
         *
         * <pre class="SqlCodeExample">
         *      CONSTRAINT_CATALOG      VARCHAR
         *      CONSTRAINT_SCHEMA       VARCHAR
         *      CONSTRAINT_NAME         VARCHAR
         *      TABLE_CATALOG           VARCHAR
         *      TABLE_SCHEMA            VARCHAR
         *      TABLE_NAME              VARCHAR
         * </pre>
         *
         * <b>Description:</b> <p>
         *
         * <ol>
         * <li> The values of CONSTRAINT_CATALOG, CONSTRAINT_SCHEMA, and
         *      CONSTRAINT_NAME are the catalog name, unqualified schema name,
         *       and qualified identifier, respectively, of the constraint being
         *      described. <p>
         *
         * <li> The values of TABLE_CATALOG, TABLE_SCHEMA, and TABLE_NAME are the
         *      catalog name, unqualified schema name, and qualified identifier,
         *      respectively, of a table identified by a &lt;table name&gt;
         *      simply contained in a &lt;table reference&gt; contained in the
         *      *lt;search condition&gt; of the constraint being described, or
         *      its columns.
         * </ol>
         *
         * @return Table
         */
        Table CONSTRAINT_TABLE_USAGE()
        {

            Table t = sysTables[ID_CONSTRAINT_TABLE_USAGE];

            if (t == null)
            {
                t = createBlankTable(sysTableHsqlNames[ID_CONSTRAINT_TABLE_USAGE]);

                addColumn(t, "CONSTRAINT_CATALOG", SQL_IDENTIFIER);
                addColumn(t, "CONSTRAINT_SCHEMA", SQL_IDENTIFIER);
                addColumn(t, "CONSTRAINT_NAME", SQL_IDENTIFIER);    // not null
                addColumn(t, "TABLE_CATALOG", SQL_IDENTIFIER);
                addColumn(t, "TABLE_SCHEMA", SQL_IDENTIFIER);
                addColumn(t, "TABLE_NAME", SQL_IDENTIFIER);         // not null

                QNameManager.QName name = QNameManager.newInfoSchemaObjectName(
                    sysTableHsqlNames[ID_CONSTRAINT_TABLE_USAGE].name, false,
                    SchemaObjectTypes.INDEX);

                t.createPrimaryKey(name, new int[] {
                0, 1, 2, 3, 4, 5
            }, false);

                return t;
            }

            PersistentStore store = database.persistentStoreCollection.getStore(t);

            //
            Session sys = database.sessionManager.newSysSession(
                SqlInvariants.INFORMATION_SCHEMA_QNAME, session.getUser());
            Result rs = sys.executeDirectStatement(
                "select DISTINCT CONSTRAINT_CATALOG, CONSTRAINT_SCHEMA, "
                + "CONSTRAINT_NAME, TABLE_CATALOG, TABLE_SCHEMA, TABLE_NAME "
                + "from INFORMATION_SCHEMA.CONSTRAINT_COLUMN_USAGE");

            t.insertSys(store, rs);
            sys.close();

            return t;
        }

        Table DATA_TYPE_PRIVILEGES()
        {

            Table t = sysTables[ID_DATA_TYPE_PRIVILEGES];

            if (t == null)
            {
                t = createBlankTable(sysTableHsqlNames[ID_DATA_TYPE_PRIVILEGES]);

                addColumn(t, "OBJECT_CATALOG", SQL_IDENTIFIER);
                addColumn(t, "OBJECT_SCHEMA", SQL_IDENTIFIER);
                addColumn(t, "OBJECT_NAME", SQL_IDENTIFIER);    // not null
                addColumn(t, "OBJECT_TYPE", SQL_IDENTIFIER);
                addColumn(t, "DTD_IDENTIFIER", SQL_IDENTIFIER);

                QNameManager.QName name = QNameManager.newInfoSchemaObjectName(
                    sysTableHsqlNames[ID_DATA_TYPE_PRIVILEGES].name, false,
                    SchemaObjectTypes.INDEX);

                t.createPrimaryKey(name, new int[] {
                0, 1, 2, 3, 4
            }, false);

                return t;
            }

            PersistentStore store = database.persistentStoreCollection.getStore(t);

            //
            Session sys = database.sessionManager.newSysSession(
                SqlInvariants.INFORMATION_SCHEMA_QNAME, session.getUser());
            String sql = (String)statementMap.get("/*data_type_privileges*/");
            Result rs = sys.executeDirectStatement(sql);

            t.insertSys(store, rs);
            sys.close();

            return t;
        }

        /**
         * a DEFINITION_SCHEMA table. Not in the INFORMATION_SCHEMA list
         */
        /*
            Table DATA_TYPE_DESCRIPTOR() {

                Table t = sysTables[DATA_TYPE_DESCRIPTOR];

                if (t == null) {
                    t = createBlankTable(sysTableHsqlNames[DATA_TYPE_DESCRIPTOR]);

                    addColumn(t, "OBJECT_CATALOG", SQL_IDENTIFIER);
                    addColumn(t, "OBJECT_SCHEMA", SQL_IDENTIFIER);
                    addColumn(t, "OBJECT_NAME", SQL_IDENTIFIER);
                    addColumn(t, "OBJECT_TYPE", CHARACTER_DATA);
                    addColumn(t, "DTD_IDENTIFIER", SQL_IDENTIFIER);
                    addColumn(t, "DATA_TYPE", CHARACTER_DATA);
                    addColumn(t, "CHARACTER_SET_CATALOG", SQL_IDENTIFIER);
                    addColumn(t, "CHARACTER_SET_SCHEMA", SQL_IDENTIFIER);
                    addColumn(t, "CHARACTER_SET_NAME", SQL_IDENTIFIER);
                    addColumn(t, "CHARACTER_MAXIMUM_LENGTH", CARDINAL_NUMBER);
                    addColumn(t, "CHARACTER_OCTET_LENGTH", CARDINAL_NUMBER);
                    addColumn(t, "COLLATION_CATALOG", SQL_IDENTIFIER);
                    addColumn(t, "COLLATION_SCHEMA", SQL_IDENTIFIER);
                    addColumn(t, "COLLATION_NAME", SQL_IDENTIFIER);
                    addColumn(t, "NUMERIC_PRECISION", CARDINAL_NUMBER);
                    addColumn(t, "NUMERIC_PRECISION_RADIX", CARDINAL_NUMBER);
                    addColumn(t, "NUMERIC_SCALE", CARDINAL_NUMBER);
                    addColumn(t, "DECLARED_DATA_TYPE", CHARACTER_DATA);
                    addColumn(t, "DECLARED_NUMERIC_PRECISION", CARDINAL_NUMBER);
                    addColumn(t, "DECLARED_NUMERIC_SCLAE", CARDINAL_NUMBER);
                    addColumn(t, "DATETIME_PRECISION", CARDINAL_NUMBER);
                    addColumn(t, "INTERVAL_TYPE", CHARACTER_DATA);
                    addColumn(t, "INTERVAL_PRECISION", CARDINAL_NUMBER);
                    addColumn(t, "USER_DEFINED_TYPE_CATALOG", SQL_IDENTIFIER);
                    addColumn(t, "USER_DEFINED_TYPE_SCHEMA", SQL_IDENTIFIER);
                    addColumn(t, "USER_DEFINED_TYPE_NAME", SQL_IDENTIFIER);
                    addColumn(t, "SCOPE_CATALOG", SQL_IDENTIFIER);
                    addColumn(t, "SCOPE_SCHEMA", SQL_IDENTIFIER);
                    addColumn(t, "SCOPE_NAME", SQL_IDENTIFIER);
                    addColumn(t, "MAXIMUM_CARDINALITY", SQL_IDENTIFIER);
                    t.createPrimaryKey(null, new int[] {
                        0, 1, 2, 4, 5, 6
                    }, false);

                    return t;
                }

                PersistentStore store = database.persistentStoreCollection.getStore(t);
                int       object_catalog             = 0;
                int       object_schema              = 1;
                int       object_name                = 2;
                int       object_type                = 3;
                int       dtd_identifier             = 4;
                int       data_type                  = 5;
                int       character_set_catalog      = 6;
                int       character_set_schema       = 7;
                int       character_set_name         = 8;
                int       character_maximum_length   = 9;
                int       character_octet_length     = 10;
                int       collation_catalog          = 11;
                int       collation_schema           = 12;
                int       collation_name             = 13;
                int       numeric_precision          = 14;
                int       numeric_precision_radix    = 15;
                int       numeric_scale              = 16;
                int       declared_data_type         = 17;
                int       declared_numeric_precision = 18;
                int       declared_numeric_scale     = 19;
                int       datetime_precision         = 20;
                int       interval_type              = 21;
                int       interval_precision         = 22;
                int       user_defined_type_catalog  = 23;
                int       user_defined_type_schema   = 24;
                int       user_defined_type_name     = 25;
                int       scope_catalog              = 26;
                int       scope_schema               = 27;
                int       scope_name                 = 28;
                int       maximum_cardinality        = 29;
                return t;
            }
        */

        /**
         *
         * @return Table
         */
        Table DOMAIN_CONSTRAINTS()
        {

            Table t = sysTables[ID_DOMAIN_CONSTRAINTS];

            if (t == null)
            {
                t = createBlankTable(sysTableHsqlNames[ID_DOMAIN_CONSTRAINTS]);

                addColumn(t, "CONSTRAINT_CATALOG", SQL_IDENTIFIER);
                addColumn(t, "CONSTRAINT_SCHEMA", SQL_IDENTIFIER);
                addColumn(t, "CONSTRAINT_NAME", SQL_IDENTIFIER);    // not null
                addColumn(t, "DOMAIN_CATALOG", SQL_IDENTIFIER);
                addColumn(t, "DOMAIN_SCHEMA", SQL_IDENTIFIER);
                addColumn(t, "DOMAIN_NAME", SQL_IDENTIFIER);
                addColumn(t, "IS_DEFERRABLE", YES_OR_NO);
                addColumn(t, "INITIALLY_DEFERRED", YES_OR_NO);

                QNameManager.QName name = QNameManager.newInfoSchemaObjectName(
                    sysTableHsqlNames[ID_DOMAIN_CONSTRAINTS].name, false,
                    SchemaObjectTypes.INDEX);

                t.createPrimaryKey(name, new int[] {
                0, 1, 2, 4, 5, 6
            }, false);

                return t;
            }

            int constraint_catalog = 0;
            int constraint_schema = 1;
            int constraint_name = 2;
            int domain_catalog = 3;
            int domain_schema = 4;
            int domain_name = 5;
            int is_deferrable = 6;
            int initially_deferred = 7;

            //
            PersistentStore store = database.persistentStoreCollection.getStore(t);

            //
            Iterator it =
                database.schemaManager.databaseObjectIterator(SchemaObjectTypes.DOMAIN);

            while (it.hasNext())
            {
                SqlType domain = (SqlType)it.next();

                if (!domain.isDomainType())
                {
                    continue;
                }

                if (!session.getGrantee().isFullyAccessibleByRole(
                        domain.getName()))
                {
                    continue;
                }

                Constraint[] constraints =
                    domain.userTypeModifier.getConstraints();

                for (int i = 0; i < constraints.Length; i++)
                {
                    Object[] data = t.getEmptyRowData();

                    data[constraint_catalog] = data[domain_catalog] =
                        database.getCatalogName().originalName;
                    data[constraint_schema] = data[domain_schema] =
                        domain.getSchemaName().originalName;
                    data[constraint_name] = constraints[i].getName().originalName;
                    data[domain_name] = domain.getName().originalName;
                    data[is_deferrable] = Tokens.T_NO;
                    data[initially_deferred] = Tokens.T_NO;

                    t.insertSys(store, data);
                }
            }

            return t;
        }

        /**
         * The DOMAINS view has one row for each domain. <p>
         *
         *
         * <pre class="SqlCodeExample">
         *
         * </pre>
         *
         * @return Table
         */
        Table DOMAINS()
        {

            Table t = sysTables[ID_DOMAINS];

            if (t == null)
            {
                t = createBlankTable(sysTableHsqlNames[ID_DOMAINS]);

                addColumn(t, "DOMAIN_CATALOG", SQL_IDENTIFIER);
                addColumn(t, "DOMAIN_SCHEMA", SQL_IDENTIFIER);
                addColumn(t, "DOMAIN_NAME", SQL_IDENTIFIER);
                addColumn(t, "DATA_TYPE", SQL_IDENTIFIER);
                addColumn(t, "CHARACTER_MAXIMUM_LENGTH", CARDINAL_NUMBER);
                addColumn(t, "CHARACTER_OCTET_LENGTH", CARDINAL_NUMBER);
                addColumn(t, "CHARACTER_SET_CATALOG", SQL_IDENTIFIER);
                addColumn(t, "CHARACTER_SET_SCHEMA", SQL_IDENTIFIER);
                addColumn(t, "CHARACTER_SET_NAME", SQL_IDENTIFIER);
                addColumn(t, "COLLATION_CATALOG", SQL_IDENTIFIER);
                addColumn(t, "COLLATION_SCHEMA", SQL_IDENTIFIER);
                addColumn(t, "COLLATION_NAME", SQL_IDENTIFIER);
                addColumn(t, "NUMERIC_PRECISION", CARDINAL_NUMBER);
                addColumn(t, "NUMERIC_PRECISION_RADIX", CARDINAL_NUMBER);
                addColumn(t, "NUMERIC_SCALE", CARDINAL_NUMBER);
                addColumn(t, "DATETIME_PRECISION", CARDINAL_NUMBER);
                addColumn(t, "INTERVAL_TYPE", CHARACTER_DATA);
                addColumn(t, "INTERVAL_PRECISION", CARDINAL_NUMBER);
                addColumn(t, "DOMAIN_DEFAULT", CHARACTER_DATA);
                addColumn(t, "MAXIMUM_CARDINALITY", SQL_IDENTIFIER);
                addColumn(t, "DTD_IDENTIFIER", SQL_IDENTIFIER);
                addColumn(t, "DECLARED_DATA_TYPE", CHARACTER_DATA);
                addColumn(t, "DECLARED_NUMERIC_PRECISION", CARDINAL_NUMBER);
                addColumn(t, "DECLARED_NUMERIC_SCLAE", CARDINAL_NUMBER);

                QNameManager.QName name = QNameManager.newInfoSchemaObjectName(
                    sysTableHsqlNames[ID_DOMAINS].name, false, SchemaObjectTypes.INDEX);

                t.createPrimaryKey(name, new int[] {
                0, 1, 2, 4, 5, 6
            }, false);

                return t;
            }

            int domain_catalog = 0;
            int domain_schema = 1;
            int domain_name = 2;
            int data_type = 3;
            int character_maximum_length = 4;
            int character_octet_length = 5;
            int character_set_catalog = 6;
            int character_set_schema = 7;
            int character_set_name = 8;
            int collation_catalog = 9;
            int collation_schema = 10;
            int collation_name = 11;
            int numeric_precision = 12;
            int numeric_precision_radix = 13;
            int numeric_scale = 14;
            int datetime_precision = 15;
            int interval_type = 16;
            int interval_precision = 17;
            int domain_default = 18;
            //int maximum_cardinality = 19;
            //int dtd_identifier = 20;
            //int declared_data_type = 21;
            int declared_numeric_precision = 22;
            int declared_numeric_scale = 23;

            //
            PersistentStore store = database.persistentStoreCollection.getStore(t);

            //
            Iterator it =
                database.schemaManager.databaseObjectIterator(SchemaObjectTypes.DOMAIN);

            while (it.hasNext())
            {
                SqlType type = (SqlType)it.next();

                if (!type.isDomainType())
                {
                    continue;
                }

                if (!session.getGrantee().isAccessible(type))
                {
                    continue;
                }

                Object[] row = t.getEmptyRowData();

                row[domain_catalog] = database.getCatalogName().originalName;
                row[domain_schema] = type.getSchemaName().originalName;
                row[domain_name] = type.getName().originalName;
                row[data_type] = type.getFullNameString();

                // common type block
                if (type.isCharacterType())
                {
                    row[character_maximum_length] =
                        (long)(type.precision);
                    row[character_octet_length] = (long)(type.precision
                            * 2);
                    row[character_set_catalog] = database.getCatalogName().originalName;
                    row[character_set_schema] =
                        ((CharacterType)type).getCharacterSet().getSchemaName()
                            .originalName;
                    row[character_set_name] =
                        ((CharacterType)type).getCharacterSet().getName().originalName;
                    row[collation_catalog] = database.getCatalogName().originalName;
                    row[collation_schema] =
                        ((CharacterType)type).getCollation().getSchemaName().originalName;
                    row[collation_name] =
                        ((CharacterType)type).getCollation().getName().originalName;
                }
                else if (type.isNumberType())
                {
                    row[numeric_precision] = (long)(
                        ((NumberType)type).getNumericPrecisionInRadix());
                    row[declared_numeric_precision] = (long)(
                        ((NumberType)type).getNumericPrecisionInRadix());

                    if (type.isExactNumberType())
                    {
                        row[numeric_scale] = row[declared_numeric_scale] =
                            (long)(type.scale);
                    }

                    row[numeric_precision_radix] =
                        (long)(type.getPrecisionRadix());
                }
                else if (type.isBooleanType()) { }
                else if (type.isDateTimeType())
                {
                    row[datetime_precision] = (long)(type.scale);
                }
                else if (type.isIntervalType())
                {
                    row[data_type] = "INTERVAL";
                    row[interval_type] =
                        IntervalType.getQualifier(type.typeCode);
                    row[interval_precision] = (long)(type.precision);
                    row[datetime_precision] = (long)(type.scale);
                }
                else if (type.isBinaryType())
                {
                    row[character_maximum_length] =
                        (long)(type.precision);
                    row[character_octet_length] =
                        (long)(type.precision);
                }
                else if (type.isBitType())
                {
                    row[character_maximum_length] =
                        (long)(type.precision);
                    row[character_octet_length] =
                        (long)(type.precision);
                }

                // end common block
                Expression defaultExpression =
                    type.userTypeModifier.getDefaultClause();

                if (defaultExpression != null)
                {
                    row[domain_default] = defaultExpression.getSQL();
                }

                t.insertSys(store, row);
            }

            return t;
        }

        /**
         * ENABLED_ROLES<p>
         *
         * <b>Function</b><p>
         *
         * Identify the enabled roles for the current SQL-session.<p>
         *
         * Definition<p>
         *
         * <pre class="SqlCodeExample">
         * CREATE RECURSIVE VIEW ENABLED_ROLES ( ROLE_NAME ) AS
         *      VALUES ( CURRENT_ROLE )
         *      UNION
         *      SELECT RAD.ROLE_NAME
         *        FROM DEFINITION_SCHEMA.ROLE_AUTHORIZATION_DESCRIPTORS RAD
         *        JOIN ENABLED_ROLES R
         *          ON RAD.GRANTEE = R.ROLE_NAME;
         *
         * GRANT SELECT ON TABLE ENABLED_ROLES
         *    TO PUBLIC WITH GRANT OPTION;
         * </pre>
         */
        Table ENABLED_ROLES()
        {

            Table t = sysTables[ID_ENABLED_ROLES];

            if (t == null)
            {
                t = createBlankTable(sysTableHsqlNames[ID_ENABLED_ROLES]);

                addColumn(t, "ROLE_NAME", SQL_IDENTIFIER);

                // true PK
                QNameManager.QName name = QNameManager.newInfoSchemaObjectName(
                    sysTableHsqlNames[ID_ENABLED_ROLES].name, false,
                    SchemaObjectTypes.INDEX);

                t.createPrimaryKey(name, new int[] { 0 }, true);

                return t;
            }

            PersistentStore store = database.persistentStoreCollection.getStore(t);

            // Intermediate holders
            Iterator grantees;
            Grantee grantee;
            Object[] row;

            // initialization
            grantees = session.getGrantee().getAllRoles().iterator();

            while (grantees.hasNext())
            {
                grantee = (Grantee)grantees.next();
                row = t.getEmptyRowData();
                row[0] = grantee.getNameString();

                t.insertSys(store, row);
            }

            return t;
        }

        Table ASSEMBLY_ASSEMBLY_USAGE()
        {

            Table t = sysTables[ID_ASSEMBLY_ASSEMBLY_USAGE];

            if (t == null)
            {
                t = createBlankTable(sysTableHsqlNames[ID_ASSEMBLY_ASSEMBLY_USAGE]);

                addColumn(t, "PATH_ASSEMBLY_CATALOG", SQL_IDENTIFIER);
                addColumn(t, "PATH_ASSEMBLY_SCHAMA", SQL_IDENTIFIER);
                addColumn(t, "PATH_ASSEMBLY_NAME", SQL_IDENTIFIER);
                addColumn(t, "ASSEMBLY_CATALOG", SQL_IDENTIFIER);
                addColumn(t, "ASSEMBLY_SCHEMA", SQL_IDENTIFIER);
                addColumn(t, "ASSEMBLY_NAME", SQL_IDENTIFIER);

                QNameManager.QName name = QNameManager.newInfoSchemaObjectName(
                    sysTableHsqlNames[ID_ASSEMBLY_ASSEMBLY_USAGE].name, false,
                    SchemaObjectTypes.INDEX);

                t.createPrimaryKey(name, new int[] {
                0, 1, 2, 3, 4, 5
            }, false);

                return t;
            }

            // column number mappings
            //int path_jar_catalog = 0;
            //int path_jar_schema = 1;
            //int path_jar_name = 2;
            //int jar_catalog = 3;
            //int jar_schema = 4;
            //int jar_name = 5;

            //
            //Iterator it;
            //Object[] row;

            return t;
        }

        Table ASSEMBLIES()
        {

            Table t = sysTables[ID_ASSEMBLIES];

            if (t == null)
            {
                t = createBlankTable(sysTableHsqlNames[ID_ASSEMBLIES]);

                addColumn(t, "ASSEMBLY_CATALOG", SQL_IDENTIFIER);
                addColumn(t, "ASSEMBLY_SCHEMA", SQL_IDENTIFIER);
                addColumn(t, "ASSEMBLY_NAME", SQL_IDENTIFIER);
                addColumn(t, "ASSEMBLY_PATH", CHARACTER_DATA);

                QNameManager.QName name = QNameManager.newInfoSchemaObjectName(
                    sysTableHsqlNames[ID_ASSEMBLIES].name, false, SchemaObjectTypes.INDEX);

                t.createPrimaryKey(name, new int[] {
                0, 1, 2, 3
            }, false);

                return t;
            }

            // column number mappings
            //int jar_catalog = 0;
            //int jar_schema = 1;
            //int jar_name = 2;
            //int jar_path = 3;

            //
            PersistentStore store = database.persistentStoreCollection.getStore(t);
            //Iterator it;
            //Object[] row;

            return t;
        }

        /**
         * Retrieves a <code>Table</code> object describing the
         * primary key and unique constraint columns of each accessible table
         * defined within this database. <p>
         *
         * Each row is a PRIMARY KEY or UNIQUE column description with the following
         * columns: <p>
         *
         * <pre class="SqlCodeExample">
         * CONSTRAINT_CATALOG              VARCHAR NULL,
         * CONSTRAINT_SCHEMA               VARCHAR NULL,
         * CONSTRAINT_NAME                 VARCHAR NOT NULL,
         * TABLE_CATALOG                   VARCHAR   table catalog
         * TABLE_SCHEMA                    VARCHAR   table schema
         * TABLE_NAME                      VARCHAR   table name
         * COLUMN_NAME                     VARCHAR   column name
         * ORDINAL_POSITION                INT
         * POSITION_IN_UNIQUE_CONSTRAINT   INT
         * </pre> <p>
         *
         * @return a <code>Table</code> object describing the visible
         *        primary key and unique columns of each accessible table
         *        defined within this database.
         */
        Table KEY_COLUMN_USAGE()
        {

            Table t = sysTables[ID_KEY_COLUMN_USAGE];

            if (t == null)
            {
                t = createBlankTable(sysTableHsqlNames[ID_KEY_COLUMN_USAGE]);

                addColumn(t, "CONSTRAINT_CATALOG", SQL_IDENTIFIER);
                addColumn(t, "CONSTRAINT_SCHEMA", SQL_IDENTIFIER);
                addColumn(t, "CONSTRAINT_NAME", SQL_IDENTIFIER);                   // not null
                addColumn(t, "TABLE_CATALOG", SQL_IDENTIFIER);
                addColumn(t, "TABLE_SCHEMA", SQL_IDENTIFIER);
                addColumn(t, "TABLE_NAME", SQL_IDENTIFIER);                        // not null
                addColumn(t, "COLUMN_NAME", SQL_IDENTIFIER);                       // not null
                addColumn(t, "ORDINAL_POSITION", CARDINAL_NUMBER);                 // not null
                addColumn(t, "POSITION_IN_UNIQUE_CONSTRAINT", CARDINAL_NUMBER);    // not null

                QNameManager.QName name = QNameManager.newInfoSchemaObjectName(
                    sysTableHsqlNames[ID_KEY_COLUMN_USAGE].name, false,
                    SchemaObjectTypes.INDEX);

                t.createPrimaryKey(name, new int[] {
                2, 1, 0, 6, 7
            }, false);

                return t;
            }

            PersistentStore store = database.persistentStoreCollection.getStore(t);

            // Intermediate holders
            Iterator tables;
            Object[] row;

            // column number mappings
            int constraint_catalog = 0;
            int constraint_schema = 1;
            int constraint_name = 2;
            int table_catalog = 3;
            int table_schema = 4;
            int table_name = 5;
            int column_name = 6;
            int ordinal_position = 7;
            int position_in_unique_constraint = 8;

            // Initialization
            tables =
                database.schemaManager.databaseObjectIterator(SchemaObjectTypes.TABLE);

            while (tables.hasNext())
            {
                Table table = (Table)tables.next();
                String tableCatalog = database.getCatalogName().originalName;
                String tableSchema = table.getSchemaName().originalName;
                String tableName = table.getName().originalName;

                /** @todo - requires access to the actual columns */
                if (table.isView() || !isAccessibleTable(table))
                {
                    continue;
                }

                Constraint[] constraints = table.getConstraints();

                for (int i = 0; i < constraints.Length; i++)
                {
                    Constraint constraint = constraints[i];

                    if (constraint.getConstraintType() == SchemaObjectConstraintTypes.PRIMARY_KEY || constraint
                            .getConstraintType() == SchemaObjectConstraintTypes
                            .UNIQUE || constraint
                            .getConstraintType() == SchemaObjectConstraintTypes
                            .FOREIGN_KEY)
                    {
                        String constraintName = constraint.getName().originalName;
                        int[] cols = constraint.getMainColumns();
                        int[] uniqueColMap = null;

                        if (constraint.getConstraintType()
                                == SchemaObjectConstraintTypes.FOREIGN_KEY)
                        {
                            Table uniqueConstTable = constraint.getMain();
                            Constraint uniqueConstraint =
                                uniqueConstTable.getConstraint(
                                    constraint.getUniqueName().originalName);
                            int[] uniqueConstIndexes =
                                uniqueConstraint.getMainColumns();

                            uniqueColMap = new int[cols.Length];

                            for (int j = 0; j < cols.Length; j++)
                            {
                                uniqueColMap[j] =
                                    ArrayUtil.find(uniqueConstIndexes, cols[j]);
                            }

                            cols = constraint.getRefColumns();
                        }

                        for (int j = 0; j < cols.Length; j++)
                        {
                            row = t.getEmptyRowData();
                            row[constraint_catalog] = tableCatalog;
                            row[constraint_schema] = tableSchema;
                            row[constraint_name] = constraintName;
                            row[table_catalog] = tableCatalog;
                            row[table_schema] = tableSchema;
                            row[table_name] = tableName;
                            row[column_name] =
                                table.getColumn(cols[j]).getName().originalName;
                            row[ordinal_position] = (j + 1);

                            if (constraint.getConstraintType()
                                    == SchemaObjectConstraintTypes.FOREIGN_KEY)
                            {
                                row[position_in_unique_constraint] =
                                    (uniqueColMap[j] + 1);
                            }

                            t.insertSys(store, row);
                        }
                    }
                }
            }

            return t;
        }

        Table METHOD_SPECIFICATION_PARAMETERS()
        {
            return null;
        }

        Table METHOD_SPECIFICATIONS()
        {
            return null;
        }

        Table MODULE_COLUMN_USAGE()
        {
            return null;
        }

        Table MODULE_PRIVILEGES()
        {
            return null;
        }

        Table MODULE_TABLE_USAGE()
        {
            return null;
        }

        Table MODULES()
        {
            return null;
        }

        Table PARAMETERS()
        {

            Table t = sysTables[ID_PARAMETERS];

            if (t == null)
            {
                t = createBlankTable(sysTableHsqlNames[ID_PARAMETERS]);

                addColumn(t, "SPECIFIC_CATALOG", SQL_IDENTIFIER);
                addColumn(t, "SPECIFIC_SCHEMA", SQL_IDENTIFIER);
                addColumn(t, "SPECIFIC_NAME", SQL_IDENTIFIER);
                addColumn(t, "ORDINAL_POSITION", CARDINAL_NUMBER);
                addColumn(t, "PARAMETER_MODE", CHARACTER_DATA);
                addColumn(t, "IS_RESULT", YES_OR_NO);
                addColumn(t, "AS_LOCATOR", YES_OR_NO);
                addColumn(t, "PARAMETER_NAME", SQL_IDENTIFIER);

                //
                addColumn(t, "FROM_SQL_SPECIFIC_CATALOG", SQL_IDENTIFIER);
                addColumn(t, "FROM_SQL_SPECIFIC_SCHEMA", SQL_IDENTIFIER);
                addColumn(t, "FROM_SQL_SPECIFIC_NAME", SQL_IDENTIFIER);

                //
                addColumn(t, "TO_SQL_SPECIFIC_CATALOG", SQL_IDENTIFIER);
                addColumn(t, "TO_SQL_SPECIFIC_SCHEMA", SQL_IDENTIFIER);
                addColumn(t, "TO_SQL_SPECIFIC_NAME", SQL_IDENTIFIER);

                //
                addColumn(t, "DATA_TYPE", CHARACTER_DATA);
                addColumn(t, "CHARACTER_MAXIMUM_LENGTH", CARDINAL_NUMBER);
                addColumn(t, "CHARACTER_OCTET_LENGTH", CARDINAL_NUMBER);
                addColumn(t, "CHARACTER_SET_CATALOG", CHARACTER_DATA);
                addColumn(t, "CHARACTER_SET_SCHEMA", SQL_IDENTIFIER);
                addColumn(t, "CHARACTER_SET_NAME", SQL_IDENTIFIER);
                addColumn(t, "COLLATION_CATALOG", SQL_IDENTIFIER);
                addColumn(t, "COLLATION_SCHEMA", SQL_IDENTIFIER);
                addColumn(t, "COLLATION_NAME", SQL_IDENTIFIER);
                addColumn(t, "NUMERIC_PRECISION", CARDINAL_NUMBER);
                addColumn(t, "NUMERIC_PRECISION_RADIX", CARDINAL_NUMBER);
                addColumn(t, "NUMERIC_SCALE", CARDINAL_NUMBER);
                addColumn(t, "DATETIME_PRECISION", CARDINAL_NUMBER);
                addColumn(t, "INTERVAL_TYPE", CHARACTER_DATA);
                addColumn(t, "INTERVAL_PRECISION", CARDINAL_NUMBER);
                addColumn(t, "UDT_CATALOG", SQL_IDENTIFIER);
                addColumn(t, "UDT_SCHEMA", SQL_IDENTIFIER);
                addColumn(t, "UDT_NAME", SQL_IDENTIFIER);
                addColumn(t, "SCOPE_CATALOG", SQL_IDENTIFIER);
                addColumn(t, "SCOPE_SCHEMA", SQL_IDENTIFIER);
                addColumn(t, "SCOPE_NAME", SQL_IDENTIFIER);
                addColumn(t, "MAXIMUM_CARDINALITY", CARDINAL_NUMBER);    // NULL
                addColumn(t, "DTD_IDENTIFIER", SQL_IDENTIFIER);
                addColumn(t, "DECLARED_DATA_TYPE", CHARACTER_DATA);
                addColumn(t, "DECLARED_NUMERIC_PRECISION", CARDINAL_NUMBER);
                addColumn(t, "DECLARED_NUMERIC_SCALE", CARDINAL_NUMBER);

                QNameManager.QName name = QNameManager.newInfoSchemaObjectName(
                    sysTableHsqlNames[ID_PARAMETERS].name, false, SchemaObjectTypes.INDEX);

                t.createPrimaryKey(name, new int[] {
                0, 1, 2, 3
            }, false);

                return t;
            }

            PersistentStore store = database.persistentStoreCollection.getStore(t);

            // column number mappings
            int specific_cat = 0;
            int specific_schem = 1;
            int specific_name = 2;
            int ordinal_position = 3;
            int parameter_mode = 4;
            int is_result = 5;
            int as_locator = 6;
            int parameter_name = 7;
            //int from_specific_catalog = 8;
            //int from_specific_schema = 9;
            //int from_specific_name = 10;
            //int to_specific_catalog = 11;
            //int to_specific_schema = 12;
            //int to_specific_name = 13;
            int data_type = 14;
            int character_maximum_length = 15;
            int character_octet_length = 16;
            int character_set_catalog = 17;
            int character_set_schema = 18;
            int character_set_name = 19;
            int collation_catalog = 20;
            int collation_schema = 21;
            int collation_name = 22;
            int numeric_precision = 23;
            int numeric_precision_radix = 24;
            //int numeric_scale = 25;
            int datetime_precision = 26;
            int interval_type = 27;
            int interval_precision = 28;
            int udt_catalog = 29;
            int udt_schema = 30;
            int udt_name = 31;
            //int scope_catalog = 32;
            //int scope_schema = 33;
            //int scope_name = 34;
            //int maximum_cardinality = 35;
            //int dtd_identifier = 36;

            // intermediate holders
            int columnCount;
            Iterator routines;
            RoutineSchema routineSchema;
            Routine routine;
            Object[] row;
            SqlType type;

            // Initialization
            routines = database.schemaManager.databaseObjectIterator(
                SchemaObjectTypes.ROUTINE);

            while (routines.hasNext())
            {
                routineSchema = (RoutineSchema)routines.next();

                if (!session.getGrantee().isAccessible(routineSchema))
                {
                    continue;
                }

                Routine[] specifics = routineSchema.getSpecificRoutines();

                for (int i = 0; i < specifics.Length; i++)
                {
                    routine = specifics[i];
                    columnCount = routine.getParameterCount();

                    for (int j = 0; j < columnCount; j++)
                    {
                        ColumnSchema column = routine.getParameter(j);

                        type = column.getDataType();
                        row = t.getEmptyRowData();
                        row[specific_cat] = database.getCatalogName().originalName;
                        row[specific_schem] = routine.getSchemaName().originalName;
                        row[specific_name] = routine.getSpecificName().originalName;
                        row[parameter_name] = column.getName().originalName;
                        row[ordinal_position] = (j + 1);

                        switch (column.getParameterMode())
                        {

                            case SchemaObjectParameterModes.PARAM_IN:
                                row[parameter_mode] = "IN";
                                break;

                            case SchemaObjectParameterModes.PARAM_OUT:
                                row[parameter_mode] = "OUT";
                                break;

                            case SchemaObjectParameterModes.PARAM_INOUT:
                                row[parameter_mode] = "INOUT";
                                break;
                        }

                        row[is_result] = "NO";
                        row[as_locator] = "NO";
                        row[data_type] = type.getFullNameString();

                        // common type block
                        if (type.isCharacterType())
                        {
                            row[character_maximum_length] =
                                (long)(type.precision);
                            row[character_octet_length] =
                                (long)(type.precision * 2);
                            row[character_set_catalog] =
                                database.getCatalogName().originalName;
                            row[character_set_schema] =
                                ((CharacterType)type).getCharacterSet()
                                    .getSchemaName().originalName;
                            row[character_set_name] =
                                ((CharacterType)type).getCharacterSet().getName()
                                    .originalName;
                            row[collation_catalog] =
                                database.getCatalogName().originalName;
                            row[collation_schema] =
                                ((CharacterType)type).getCollation()
                                    .getSchemaName().originalName;
                            row[collation_name] =
                                ((CharacterType)type).getCollation().getName()
                                    .originalName;
                        }
                        else if (type.isNumberType())
                        {
                            row[numeric_precision] = (long)(
                                ((NumberType)type).getNumericPrecisionInRadix());
                            row[numeric_precision_radix] =
                                (long)(type.getPrecisionRadix());
                        }
                        else if (type.isBooleanType()) { }
                        else if (type.isDateTimeType())
                        {
                            row[datetime_precision] =
                                (long)(type.scale);
                        }
                        else if (type.isIntervalType())
                        {
                            row[data_type] = "INTERVAL";
                            row[interval_type] =
                                IntervalType.getQualifier(type.typeCode);
                            row[interval_precision] =
                                (long)(type.precision);
                            row[datetime_precision] =
                                (long)(type.scale);
                        }
                        else if (type.isBinaryType())
                        {
                            row[character_maximum_length] =
                                (long)(type.precision);
                            row[character_octet_length] =
                                (long)(type.precision);
                        }
                        else if (type.isBitType())
                        {
                            row[character_maximum_length] =
                                (long)(type.precision);
                            row[character_octet_length] =
                                (long)(type.precision);
                        }

                        if (type.isDistinctType())
                        {
                            row[udt_catalog] = database.getCatalogName().originalName;
                            row[udt_schema] = type.getSchemaName().originalName;
                            row[udt_name] = type.getName().originalName;
                        }

                        // end common block
                        t.insertSys(store, row);
                    }
                }
            }

            return t;
        }

        /**
         * <ol>
         * <li> A constraint is shown in this view if the user has table level
         * privilege of at lease one of the types, INSERT, UPDATE, DELETE,
         * REFERENCES or TRIGGER.
         * </ol>
         *
         * @return Table
         */
        Table REFERENTIAL_CONSTRAINTS()
        {

            Table t = sysTables[ID_REFERENTIAL_CONSTRAINTS];

            if (t == null)
            {
                t = createBlankTable(sysTableHsqlNames[ID_REFERENTIAL_CONSTRAINTS]);

                addColumn(t, "CONSTRAINT_CATALOG", SQL_IDENTIFIER);
                addColumn(t, "CONSTRAINT_SCHEMA", SQL_IDENTIFIER);
                addColumn(t, "CONSTRAINT_NAME", SQL_IDENTIFIER);              // not null
                addColumn(t, "UNIQUE_CONSTRAINT_CATALOG", SQL_IDENTIFIER);    // not null
                addColumn(t, "UNIQUE_CONSTRAINT_SCHEMA", SQL_IDENTIFIER);
                addColumn(t, "UNIQUE_CONSTRAINT_NAME", SQL_IDENTIFIER);
                addColumn(t, "MATCH_OPTION", CHARACTER_DATA);                 // not null
                addColumn(t, "UPDATE_RULE", CHARACTER_DATA);                  // not null
                addColumn(t, "DELETE_RULE", CHARACTER_DATA);                  // not null

                QNameManager.QName name = QNameManager.newInfoSchemaObjectName(
                    sysTableHsqlNames[ID_REFERENTIAL_CONSTRAINTS].name, false,
                    SchemaObjectTypes.INDEX);

                t.createPrimaryKey(name, new int[] {
                0, 1, 2,
            }, false);

                return t;
            }

            // column number mappings
            int constraint_catalog = 0;
            int constraint_schema = 1;
            int constraint_name = 2;
            int unique_constraint_catalog = 3;
            int unique_constraint_schema = 4;
            int unique_constraint_name = 5;
            int match_option = 6;
            int update_rule = 7;
            int delete_rule = 8;

            //
            PersistentStore store = database.persistentStoreCollection.getStore(t);
            Iterator tables;
            Table table;
            Constraint[] constraints;
            Constraint constraint;
            Object[] row;

            tables =
                database.schemaManager.databaseObjectIterator(SchemaObjectTypes.TABLE);

            while (tables.hasNext())
            {
                table = (Table)tables.next();

                if (table.isView()
                        || !session.getGrantee().hasNonSelectTableRight(table))
                {
                    continue;
                }

                constraints = table.getConstraints();

                for (int i = 0; i < constraints.Length; i++)
                {
                    constraint = constraints[i];

                    if (constraint.getConstraintType()
                            != SchemaObjectConstraintTypes.FOREIGN_KEY)
                    {
                        continue;
                    }

                    QNameManager.QName uniqueName = constraint.getUniqueName();

                    row = t.getEmptyRowData();
                    row[constraint_catalog] = database.getCatalogName().originalName;
                    row[constraint_schema] = constraint.getSchemaName().originalName;
                    row[constraint_name] = constraint.getName().originalName;

                    if (isAccessibleTable(constraint.getMain()))
                    {
                        row[unique_constraint_catalog] =
                            database.getCatalogName().originalName;
                        row[unique_constraint_schema] = uniqueName.schema.originalName;
                        row[unique_constraint_name] = uniqueName.originalName;
                    }

                    row[match_option] = Tokens.T_NONE;
                    row[update_rule] = constraint.getUpdateActionString();
                    row[delete_rule] = constraint.getDeleteActionString();

                    t.insertSys(store, row);
                }
            }

            return t;
        }

        Table ROLE_COLUMN_GRANTS()
        {

            Table t = sysTables[ID_ROLE_COLUMN_GRANTS];

            if (t == null)
            {
                t = createBlankTable(sysTableHsqlNames[ID_ROLE_COLUMN_GRANTS]);

                addColumn(t, "GRANTOR", SQL_IDENTIFIER);           // not null
                addColumn(t, "GRANTEE", SQL_IDENTIFIER);           // not null
                addColumn(t, "TABLE_CATALOG", SQL_IDENTIFIER);
                addColumn(t, "TABLE_SCHEMA", SQL_IDENTIFIER);
                addColumn(t, "TABLE_NAME", SQL_IDENTIFIER);        // not null
                addColumn(t, "COLUMN_NAME", SQL_IDENTIFIER);       // not null
                addColumn(t, "PRIVILEGE_TYPE", CHARACTER_DATA);    // not null
                addColumn(t, "IS_GRANTABLE", YES_OR_NO);           // not null

                // order: COLUMN_NAME, PRIVILEGE
                // for unique: GRANTEE, GRANTOR, TABLE_NAME, TABLE_SCHEMA, TABLE_CAT
                // false PK, as TABLE_SCHEMA and/or TABLE_CAT may be null
                QNameManager.QName name = QNameManager.newInfoSchemaObjectName(
                    sysTableHsqlNames[ID_ROLE_COLUMN_GRANTS].name, false,
                    SchemaObjectTypes.INDEX);

                t.createPrimaryKey(name, new int[] {
                5, 6, 1, 0, 4, 3, 2
            }, false);

                return t;
            }

            PersistentStore store = database.persistentStoreCollection.getStore(t);
            Session sys = database.sessionManager.newSysSession(
                SqlInvariants.INFORMATION_SCHEMA_QNAME, session.getUser());
            Result rs = sys.executeDirectStatement(
                "SELECT GRANTOR, GRANTEE, TABLE_CATALOG, TABLE_SCHEMA, TABLE_NAME, COLUMN_NAME, PRIVILEGE_TYPE, IS_GRANTABLE "
                + "FROM INFORMATION_SCHEMA.COLUMN_PRIVILEGES "
                + "JOIN INFORMATION_SCHEMA.APPLICABLE_ROLES ON GRANTEE = ROLE_NAME;");

            t.insertSys(store, rs);
            sys.close();

            return t;
        }

        Table ROLE_ROUTINE_GRANTS()
        {

            Table t = sysTables[ID_ROLE_ROUTINE_GRANTS];

            if (t == null)
            {
                t = createBlankTable(sysTableHsqlNames[ID_ROLE_ROUTINE_GRANTS]);

                addColumn(t, "GRANTOR", SQL_IDENTIFIER);          // not null
                addColumn(t, "GRANTEE", SQL_IDENTIFIER);          // not null
                addColumn(t, "SPECIFIC_CATALOG", SQL_IDENTIFIER);
                addColumn(t, "SPECIFIC_SCHEMA", SQL_IDENTIFIER);
                addColumn(t, "SPECIFIC_NAME", SQL_IDENTIFIER);    // not null
                addColumn(t, "ROUTINE_CATALOG", SQL_IDENTIFIER);
                addColumn(t, "ROUTINE_SCHEMA", SQL_IDENTIFIER);
                addColumn(t, "ROUTINE_NAME", SQL_IDENTIFIER);
                addColumn(t, "PRIVILEGE_TYPE", CHARACTER_DATA);
                addColumn(t, "IS_GRANTABLE", YES_OR_NO);

                QNameManager.QName name = QNameManager.newInfoSchemaObjectName(
                    sysTableHsqlNames[ID_ROLE_ROUTINE_GRANTS].name, false,
                    SchemaObjectTypes.INDEX);

                t.createPrimaryKey(name, new int[] {
                0, 1, 2, 3, 4, 5, 6, 7, 8, 9
            }, false);

                return t;
            }

            PersistentStore store = database.persistentStoreCollection.getStore(t);
            Session sys = database.sessionManager.newSysSession(
                SqlInvariants.INFORMATION_SCHEMA_QNAME, session.getUser());
            Result rs = sys.executeDirectStatement(
                "SELECT GRANTOR, GRANTEE, SPECIFIC_CATALOG, SPECIFIC_SCHEMA, "
                + "SPECIFIC_NAME, ROUTINE_CATALOG, ROUTINE_SCHEMA, ROUTINE_NAME, "
                + "PRIVILEGE_TYPE, IS_GRANTABLE "
                + "FROM INFORMATION_SCHEMA.ROUTINE_PRIVILEGES "
                + "JOIN INFORMATION_SCHEMA.APPLICABLE_ROLES ON GRANTEE = ROLE_NAME;");

            t.insertSys(store, rs);
            sys.close();

            // Column number mappings
            //int grantor = 0;
            //int grantee = 1;
            //int table_name = 2;
            //int specific_catalog = 3;
            //int specific_schema = 4;
            //int specific_name = 5;
            //int routine_catalog = 6;
            //int routine_schema = 7;
            //int routine_name = 8;
            //int privilege_type = 9;
            //int is_grantable = 10;

            //
            return t;
        }

        Table ROLE_TABLE_GRANTS()
        {

            Table t = sysTables[ID_ROLE_TABLE_GRANTS];

            if (t == null)
            {
                t = createBlankTable(sysTableHsqlNames[ID_ROLE_TABLE_GRANTS]);

                addColumn(t, "GRANTOR", SQL_IDENTIFIER);           // not null
                addColumn(t, "GRANTEE", SQL_IDENTIFIER);           // not null
                addColumn(t, "TABLE_CATALOG", SQL_IDENTIFIER);
                addColumn(t, "TABLE_SCHEMA", SQL_IDENTIFIER);
                addColumn(t, "TABLE_NAME", SQL_IDENTIFIER);        // not null
                addColumn(t, "PRIVILEGE_TYPE", CHARACTER_DATA);    // not null
                addColumn(t, "IS_GRANTABLE", YES_OR_NO);           // not null
                addColumn(t, "WITH_HIERARCHY", YES_OR_NO);

                // order:  TABLE_SCHEM, TABLE_NAME, and PRIVILEGE,
                // added for unique:  GRANTEE, GRANTOR,
                // false PK, as TABLE_SCHEM and/or TABLE_CAT may be null
                QNameManager.QName name = QNameManager.newInfoSchemaObjectName(
                    sysTableHsqlNames[ID_ROLE_TABLE_GRANTS].name, false,
                    SchemaObjectTypes.INDEX);

                t.createPrimaryKey(name, new int[] {
                3, 4, 5, 0, 1
            }, false);

                return t;
            }

            PersistentStore store = database.persistentStoreCollection.getStore(t);
            Session sys = database.sessionManager.newSysSession(
                SqlInvariants.INFORMATION_SCHEMA_QNAME, session.getUser());
            Result rs = sys.executeDirectStatement(
                "SELECT GRANTOR, GRANTEE, TABLE_CATALOG, TABLE_SCHEMA, TABLE_NAME, "
                + "PRIVILEGE_TYPE, IS_GRANTABLE, 'NO' "
                + "FROM INFORMATION_SCHEMA.TABLE_PRIVILEGES "
                + "JOIN INFORMATION_SCHEMA.APPLICABLE_ROLES ON GRANTEE = ROLE_NAME;");

            t.insertSys(store, rs);
            sys.close();

            return t;
        }

        Table ROLE_UDT_GRANTS()
        {

            Table t = sysTables[ID_ROLE_UDT_GRANTS];

            if (t == null)
            {
                t = createBlankTable(sysTableHsqlNames[ID_ROLE_UDT_GRANTS]);

                addColumn(t, "GRANTOR", SQL_IDENTIFIER);     // not null
                addColumn(t, "GRANTEE", SQL_IDENTIFIER);     // not null
                addColumn(t, "UDT_CATALOG", SQL_IDENTIFIER);
                addColumn(t, "UDT_SCHEMA", SQL_IDENTIFIER);
                addColumn(t, "UDT_NAME", SQL_IDENTIFIER);    // not null
                addColumn(t, "PRIVILEGE_TYPE", CHARACTER_DATA);
                addColumn(t, "IS_GRANTABLE", YES_OR_NO);     // not null

                QNameManager.QName name = QNameManager.newInfoSchemaObjectName(
                    sysTableHsqlNames[ID_ROLE_TABLE_GRANTS].name, false,
                    SchemaObjectTypes.INDEX);

                t.createPrimaryKey(name, null, false);

                return t;
            }

            PersistentStore store = database.persistentStoreCollection.getStore(t);
            Session sys = database.sessionManager.newSysSession(
                SqlInvariants.INFORMATION_SCHEMA_QNAME, session.getUser());
            Result rs = sys.executeDirectStatement(
                "SELECT GRANTOR, GRANTEE, UDT_CATALOG, UDT_SCHEMA, UDT_NAME, "
                + "PRIVILEGE_TYPE, IS_GRANTABLE "
                + "FROM INFORMATION_SCHEMA.UDT_PRIVILEGES "
                + "JOIN INFORMATION_SCHEMA.APPLICABLE_ROLES ON GRANTEE = ROLE_NAME;");

            t.insertSys(store, rs);
            sys.close();

            return t;
        }

        Table ROLE_USAGE_GRANTS()
        {

            Table t = sysTables[ID_ROLE_USAGE_GRANTS];

            if (t == null)
            {
                t = createBlankTable(sysTableHsqlNames[ID_ROLE_USAGE_GRANTS]);

                addColumn(t, "GRANTOR", SQL_IDENTIFIER);        // not null
                addColumn(t, "GRANTEE", SQL_IDENTIFIER);        // not null
                addColumn(t, "OBJECT_CATALOG", SQL_IDENTIFIER);
                addColumn(t, "OBJECT_SCHEMA", SQL_IDENTIFIER);
                addColumn(t, "OBJECT_NAME", SQL_IDENTIFIER);    // not null
                addColumn(t, "OBJECT_TYPE", CHARACTER_DATA);    // not null
                addColumn(t, "PRIVILEGE_TYPE", CHARACTER_DATA);
                addColumn(t, "IS_GRANTABLE", YES_OR_NO);        // not null

                QNameManager.QName name = QNameManager.newInfoSchemaObjectName(
                    sysTableHsqlNames[ID_ROLE_USAGE_GRANTS].name, false,
                    SchemaObjectTypes.INDEX);

                t.createPrimaryKey(name, new int[] {
                0, 1, 2, 3, 4, 5, 6, 7
            }, false);

                return t;
            }

            PersistentStore store = database.persistentStoreCollection.getStore(t);
            Session sys = database.sessionManager.newSysSession(
                SqlInvariants.INFORMATION_SCHEMA_QNAME, session.getUser());
            Result rs = sys.executeDirectStatement(
                "SELECT GRANTOR, GRANTEE, OBJECT_CATALOG, OBJECT_SCHEMA, OBJECT_NAME, "
                + "OBJECT_TYPE, PRIVILEGE_TYPE, IS_GRANTABLE "
                + "FROM INFORMATION_SCHEMA.USAGE_PRIVILEGES "
                + "JOIN INFORMATION_SCHEMA.APPLICABLE_ROLES ON GRANTEE = ROLE_NAME;");

            t.insertSys(store, rs);
            sys.close();

            return t;
        }

        Table ROUTINE_COLUMN_USAGE()
        {

            Table t = sysTables[ID_ROUTINE_COLUMN_USAGE];

            if (t == null)
            {
                t = createBlankTable(sysTableHsqlNames[ID_ROUTINE_COLUMN_USAGE]);

                addColumn(t, "SPECIFIC_CATALOG", SQL_IDENTIFIER);
                addColumn(t, "SPECIFIC_SCHEMA", SQL_IDENTIFIER);
                addColumn(t, "SPECIFIC_NAME", SQL_IDENTIFIER);
                addColumn(t, "ROUTINE_CATALOG", SQL_IDENTIFIER);
                addColumn(t, "ROUTINE_SCHEMA", SQL_IDENTIFIER);
                addColumn(t, "ROUTINE_NAME", SQL_IDENTIFIER);
                addColumn(t, "TABLE_CATALOG", SQL_IDENTIFIER);
                addColumn(t, "TABLE_SCHEMA", SQL_IDENTIFIER);
                addColumn(t, "TABLE_NAME", SQL_IDENTIFIER);
                addColumn(t, "COLUMN_NAME", SQL_IDENTIFIER);

                QNameManager.QName name = QNameManager.newInfoSchemaObjectName(
                    sysTableHsqlNames[ID_ROUTINE_COLUMN_USAGE].name, false,
                    SchemaObjectTypes.INDEX);

                t.createPrimaryKey(name, new int[] {
                3, 4, 5, 0, 1, 2, 6, 7, 8, 9
            }, false);

                return t;
            }

            PersistentStore store = database.persistentStoreCollection.getStore(t);

            // column number mappings
            int specific_catalog = 0;
            int specific_schema = 1;
            int specific_name = 2;
            int routine_catalog = 3;
            int routine_schema = 4;
            int routine_name = 5;
            int table_catalog = 6;
            int table_schema = 7;
            int table_name = 8;
            int column_name = 9;

            //
            Iterator it;
            Object[] row;

            it = database.schemaManager.databaseObjectIterator(
                SchemaObjectTypes.ROUTINE);

            while (it.hasNext())
            {
                RoutineSchema routine = (RoutineSchema)it.next();

                if (!session.getGrantee().isAccessible(routine))
                {
                    continue;
                }

                Routine[] specifics = routine.getSpecificRoutines();

                for (int m = 0; m < specifics.Length; m++)
                {
                    OrderedHashSet set = specifics[m].getReferences();

                    for (int i = 0; i < set.size(); i++)
                    {
                        QNameManager.QName refName = (QNameManager.QName)set.get(i);

                        if (refName.type != SchemaObjectTypes.COLUMN)
                        {
                            continue;
                        }

                        if (!session.getGrantee().isAccessible(refName))
                        {
                            continue;
                        }

                        row = t.getEmptyRowData();

                        //
                        row[specific_catalog] = database.getCatalogName().originalName;
                        row[specific_schema] = specifics[m].getSchemaName().originalName;
                        row[specific_name] = specifics[m].getSpecificName().originalName;
                        row[routine_catalog] = database.getCatalogName().originalName;
                        row[routine_schema] = routine.getSchemaName().originalName;
                        row[routine_name] = routine.getName().originalName;
                        row[table_catalog] = database.getCatalogName().originalName;
                        row[table_schema] = refName.parent.schema.originalName;
                        row[table_name] = refName.parent.originalName;
                        row[column_name] = refName.originalName;

                        try
                        {
                            t.insertSys(store, row);
                        }
                        catch (CoreException ) { }
                    }
                }
            }

            return t;
        }

        Table ROUTINE_PRIVILEGES()
        {

            Table t = sysTables[ID_ROUTINE_PRIVILEGES];

            if (t == null)
            {
                t = createBlankTable(sysTableHsqlNames[ID_ROUTINE_PRIVILEGES]);

                addColumn(t, "GRANTOR", SQL_IDENTIFIER);           // not null
                addColumn(t, "GRANTEE", SQL_IDENTIFIER);           // not null
                addColumn(t, "SPECIFIC_CATALOG", SQL_IDENTIFIER);
                addColumn(t, "SPECIFIC_SCHEMA", SQL_IDENTIFIER);
                addColumn(t, "SPECIFIC_NAME", SQL_IDENTIFIER);     // not null
                addColumn(t, "ROUTINE_CATALOG", SQL_IDENTIFIER);
                addColumn(t, "ROUTINE_SCHEMA", SQL_IDENTIFIER);
                addColumn(t, "ROUTINE_NAME", SQL_IDENTIFIER);      // not null
                addColumn(t, "PRIVILEGE_TYPE", CHARACTER_DATA);    // not null
                addColumn(t, "IS_GRANTABLE", YES_OR_NO);           // not null

                //
                QNameManager.QName name = QNameManager.newInfoSchemaObjectName(
                    sysTableHsqlNames[ID_ROUTINE_PRIVILEGES].name, false,
                    SchemaObjectTypes.INDEX);

                t.createPrimaryKey(name, new int[] {
                0, 1, 2, 3, 4, 5, 6, 7, 8, 9
            }, false);

                return t;
            }

            // column number mappings
            int grantor = 0;
            int grantee = 1;
            int specific_catalog = 2;
            int specific_schema = 3;
            int specific_name = 4;
            int routine_catalog = 5;
            int routine_schema = 6;
            int routine_name = 7;
            int privilege_type = 8;
            int is_grantable = 9;

            //
            PersistentStore store = database.persistentStoreCollection.getStore(t);

            // calculated column values
            Grantee granteeObject;
            String privilege;

            // intermediate holders
            Iterator routines;
            RoutineSchema routine;
            Object[] row;
            OrderedHashSet grantees =
                session.getGrantee().getGranteeAndAllRolesWithPublic();

            routines = database.schemaManager.databaseObjectIterator(
                SchemaObjectTypes.ROUTINE);

            while (routines.hasNext())
            {
                routine = (RoutineSchema)routines.next();

                for (int i = 0; i < grantees.size(); i++)
                {
                    granteeObject = (Grantee)grantees.get(i);

                    OrderedHashSet rights =
                        granteeObject.getAllDirectPrivileges(routine);
                    OrderedHashSet grants =
                        granteeObject.getAllGrantedPrivileges(routine);

                    if (!grants.isEmpty())
                    {
                        grants.addAll(rights);

                        rights = grants;
                    }

                    for (int j = 0; j < rights.size(); j++)
                    {
                        Right right = (Right)rights.get(j);
                        Right grantableRight = right.getGrantableRights();

                        for (int k = 0; k < Right.privilegeTypes.Length; k++)
                        {
                            if (!right.canAccessFully(Right.privilegeTypes[k]))
                            {
                                continue;
                            }

                            Routine[] specifics = routine.getSpecificRoutines();

                            for (int m = 0; m < specifics.Length; m++)
                            {
                                privilege = Right.privilegeNames[k];
                                row = t.getEmptyRowData();

                                //
                                row[grantor] = right.getGrantor().getName().originalName;
                                row[grantee] = right.getGrantee().getName().originalName;
                                row[specific_catalog] =
                                    database.getCatalogName().originalName;
                                row[specific_schema] =
                                    specifics[m].getSchemaName().originalName;
                                row[specific_name] =
                                    specifics[m].getSpecificName().originalName;
                                row[routine_catalog] =
                                    database.getCatalogName().originalName;
                                row[routine_schema] = routine.getSchemaName().originalName;
                                row[routine_name] = routine.getName().originalName;
                                row[privilege_type] = privilege;
                                row[is_grantable] =
                                    right.getGrantee() == routine.getOwner()
                                    || grantableRight.canAccessFully(
                                        Right.privilegeTypes[k]) ? "YES"
                                                                 : "NO";

                                try
                                {
                                    t.insertSys(store, row);
                                }
                                catch (CoreException ) { }
                            }
                        }
                    }
                }
            }

            return t;
        }

        Table ROUTINE_ASSEMBLY_USAGE()
        {

            Table t = sysTables[ID_ROUTINE_ASSEMBLY_USAGE];

            if (t == null)
            {
                t = createBlankTable(sysTableHsqlNames[ID_ROUTINE_ASSEMBLY_USAGE]);

                addColumn(t, "SPECIFIC_CATALOG", SQL_IDENTIFIER);
                addColumn(t, "SPECIFIC_SCHEMA", SQL_IDENTIFIER);
                addColumn(t, "SPECIFIC_NAME", SQL_IDENTIFIER);
                addColumn(t, "ASSEMBLY_CATALOG", SQL_IDENTIFIER);
                addColumn(t, "ASSEMBLY_SCHEMA", SQL_IDENTIFIER);
                addColumn(t, "ASSEMBLY_NAME", SQL_IDENTIFIER);

                QNameManager.QName name = QNameManager.newInfoSchemaObjectName(
                    sysTableHsqlNames[ID_ROUTINE_ASSEMBLY_USAGE].name, false,
                    SchemaObjectTypes.INDEX);

                t.createPrimaryKey(name, new int[] {
                0, 1, 2, 3, 4, 5
            }, false);

                return t;
            }

            // column number mappings
            int specific_catalog = 0;
            int specific_schema = 1;
            int specific_name = 2;
            int jar_catalog = 3;
            int jar_schema = 4;
            int jar_name = 5;

            //
            Iterator it;
            Object[] row;
            PersistentStore store = database.persistentStoreCollection.getStore(t);

            it = database.schemaManager.databaseObjectIterator(
                SchemaObjectTypes.ROUTINE);

            while (it.hasNext())
            {
                RoutineSchema routine = (RoutineSchema)it.next();

                if (!session.getGrantee().isAccessible(routine))
                {
                    continue;
                }

                Routine[] specifics = routine.getSpecificRoutines();

                for (int m = 0; m < specifics.Length; m++)
                {
                    if (specifics[m].getLanguage() != Routine.LANGUAGE_JAVA)
                    {
                        continue;
                    }

                    row = t.getEmptyRowData();
                    row[specific_catalog] = database.getCatalogName().originalName;
                    row[specific_schema] = routine.getSchemaName().originalName;
                    row[specific_name] = routine.getName().originalName;
                    row[jar_catalog] = database.getCatalogName().originalName;
                    row[jar_schema] =
                        database.schemaManager.getSQLJSchemaHsqlName();
                    row[jar_name] = "CLASSPATH";

                    t.insertSys(store, row);
                }
            }

            return t;
        }

        /**
         * needs to provide list of specific referenced routines
         */
        Table ROUTINE_ROUTINE_USAGE()
        {

            Table t = sysTables[ID_ROUTINE_ROUTINE_USAGE];

            if (t == null)
            {
                t = createBlankTable(sysTableHsqlNames[ID_ROUTINE_ROUTINE_USAGE]);

                addColumn(t, "SPECIFIC_CATALOG", SQL_IDENTIFIER);
                addColumn(t, "SPECIFIC_SCHEMA", SQL_IDENTIFIER);
                addColumn(t, "SPECIFIC_NAME", SQL_IDENTIFIER);
                addColumn(t, "ROUTINE_CATALOG", SQL_IDENTIFIER);
                addColumn(t, "ROUTINE_SCHEMA", SQL_IDENTIFIER);
                addColumn(t, "ROUTINE_NAME", SQL_IDENTIFIER);

                QNameManager.QName name = QNameManager.newInfoSchemaObjectName(
                    sysTableHsqlNames[ID_ROUTINE_ROUTINE_USAGE].name, false,
                    SchemaObjectTypes.INDEX);

                t.createPrimaryKey(name, new int[] {
                0, 1, 2, 3, 4, 5
            }, false);

                return t;
            }

            // column number mappings
            int specific_catalog = 0;
            int specific_schema = 1;
            int specific_name = 2;
            int routine_catalog = 3;
            int routine_schema = 4;
            int routine_name = 5;

            //
            PersistentStore store = database.persistentStoreCollection.getStore(t);
            Iterator it;
            Object[] row;

            it = database.schemaManager.databaseObjectIterator(
                SchemaObjectTypes.ROUTINE);

            while (it.hasNext())
            {
                RoutineSchema routine = (RoutineSchema)it.next();

                if (!session.getGrantee().isAccessible(routine))
                {
                    continue;
                }

                Routine[] specifics = routine.getSpecificRoutines();

                for (int m = 0; m < specifics.Length; m++)
                {
                    OrderedHashSet set = specifics[m].getReferences();

                    for (int i = 0; i < set.size(); i++)
                    {
                        QNameManager.QName refName = (QNameManager.QName)set.get(i);

                        if (refName.type != SchemaObjectTypes.SPECIFIC_ROUTINE)
                        {
                            continue;
                        }

                        if (!session.getGrantee().isAccessible(refName))
                        {
                            continue;
                        }

                        row = t.getEmptyRowData();
                        row[specific_catalog] = database.getCatalogName().originalName;
                        row[specific_schema] = specifics[m].getSchemaName().originalName;
                        row[specific_name] = specifics[m].getSpecificName().originalName;
                        row[routine_catalog] = database.getCatalogName().originalName;
                        row[routine_schema] = refName.schema.originalName;
                        row[routine_name] = refName.originalName;

                        try
                        {
                            t.insertSys(store, row);
                        }
                        catch (CoreException ) { }
                    }
                }
            }

            return t;
        }

        Table ROUTINE_SEQUENCE_USAGE()
        {

            Table t = sysTables[ID_ROUTINE_SEQUENCE_USAGE];

            if (t == null)
            {
                t = createBlankTable(sysTableHsqlNames[ID_ROUTINE_SEQUENCE_USAGE]);

                addColumn(t, "SPECIFIC_CATALOG", SQL_IDENTIFIER);
                addColumn(t, "SPECIFIC_SCHEMA", SQL_IDENTIFIER);
                addColumn(t, "SPECIFIC_NAME", SQL_IDENTIFIER);
                addColumn(t, "SEQUENCE_CATALOG", SQL_IDENTIFIER);
                addColumn(t, "SEQUENCE_SCHEMA", SQL_IDENTIFIER);
                addColumn(t, "SEQUENCE_NAME", SQL_IDENTIFIER);

                QNameManager.QName name = QNameManager.newInfoSchemaObjectName(
                    sysTableHsqlNames[ID_ROUTINE_SEQUENCE_USAGE].name, false,
                    SchemaObjectTypes.INDEX);

                t.createPrimaryKey(name, new int[] {
                0, 1, 2, 3, 4, 5
            }, false);

                return t;
            }

            // column number mappings
            int specific_catalog = 0;
            int specific_schema = 1;
            int specific_name = 2;
            int sequence_catalog = 3;
            int sequence_schema = 4;
            int sequence_name = 5;

            //
            PersistentStore store = database.persistentStoreCollection.getStore(t);
            Iterator it;
            Object[] row;

            it = database.schemaManager.databaseObjectIterator(
                SchemaObjectTypes.ROUTINE);

            while (it.hasNext())
            {
                RoutineSchema routine = (RoutineSchema)it.next();

                if (!session.getGrantee().isAccessible(routine))
                {
                    continue;
                }

                Routine[] specifics = routine.getSpecificRoutines();

                for (int m = 0; m < specifics.Length; m++)
                {
                    OrderedHashSet set = specifics[m].getReferences();

                    for (int i = 0; i < set.size(); i++)
                    {
                        QNameManager.QName refName = (QNameManager.QName)set.get(i);

                        if (refName.type != SchemaObjectTypes.SEQUENCE)
                        {
                            continue;
                        }

                        if (!session.getGrantee().isAccessible(refName))
                        {
                            continue;
                        }

                        row = t.getEmptyRowData();
                        row[specific_catalog] = database.getCatalogName().originalName;
                        row[specific_schema] = specifics[m].getSchemaName().originalName;
                        row[specific_name] = specifics[m].getSpecificName().originalName;
                        row[sequence_catalog] = database.getCatalogName().originalName;
                        row[sequence_schema] = refName.schema.originalName;
                        row[sequence_name] = refName.originalName;

                        try
                        {
                            t.insertSys(store, row);
                        }
                        catch (CoreException ) { }
                    }
                }
            }

            return t;
        }

        Table ROUTINE_TABLE_USAGE()
        {

            Table t = sysTables[ID_ROUTINE_TABLE_USAGE];

            if (t == null)
            {
                t = createBlankTable(sysTableHsqlNames[ID_ROUTINE_TABLE_USAGE]);

                addColumn(t, "SPECIFIC_CATALOG", SQL_IDENTIFIER);
                addColumn(t, "SPECIFIC_SCHEMA", SQL_IDENTIFIER);
                addColumn(t, "SPECIFIC_NAME", SQL_IDENTIFIER);
                addColumn(t, "ROUTINE_CATALOG", SQL_IDENTIFIER);
                addColumn(t, "ROUTINE_SCHEMA", SQL_IDENTIFIER);
                addColumn(t, "ROUTINE_NAME", SQL_IDENTIFIER);
                addColumn(t, "TABLE_CATALOG", SQL_IDENTIFIER);
                addColumn(t, "TABLE_SCHEMA", SQL_IDENTIFIER);
                addColumn(t, "TABLE_NAME", SQL_IDENTIFIER);

                QNameManager.QName name = QNameManager.newInfoSchemaObjectName(
                    sysTableHsqlNames[ID_ROUTINE_TABLE_USAGE].name, false,
                    SchemaObjectTypes.INDEX);

                t.createPrimaryKey(name, new int[] {
                3, 4, 5, 0, 1, 2, 6, 7, 8
            }, false);

                return t;
            }

            // column number mappings
            int specific_catalog = 0;
            int specific_schema = 1;
            int specific_name = 2;
            int routine_catalog = 3;
            int routine_schema = 4;
            int routine_name = 5;
            int table_catalog = 6;
            int table_schema = 7;
            int table_name = 8;

            //
            PersistentStore store = database.persistentStoreCollection.getStore(t);
            Iterator it;
            Object[] row;

            it = database.schemaManager.databaseObjectIterator(
                SchemaObjectTypes.ROUTINE);

            while (it.hasNext())
            {
                RoutineSchema routine = (RoutineSchema)it.next();

                if (!session.getGrantee().isAccessible(routine))
                {
                    continue;
                }

                Routine[] specifics = routine.getSpecificRoutines();

                for (int m = 0; m < specifics.Length; m++)
                {
                    OrderedHashSet set = specifics[m].getReferences();

                    for (int i = 0; i < set.size(); i++)
                    {
                        QNameManager.QName refName = (QNameManager.QName)set.get(i);

                        if (refName.type != SchemaObjectTypes.TABLE
                                && refName.type != SchemaObjectTypes.VIEW)
                        {
                            continue;
                        }

                        if (!session.getGrantee().isAccessible(refName))
                        {
                            continue;
                        }

                        row = t.getEmptyRowData();
                        row[specific_catalog] = database.getCatalogName().originalName;
                        row[specific_schema] = specifics[m].getSchemaName().originalName;
                        row[specific_name] = specifics[m].getSpecificName().originalName;
                        row[routine_catalog] = database.getCatalogName().originalName;
                        row[routine_schema] = routine.getSchemaName().originalName;
                        row[routine_name] = routine.getName().originalName;
                        row[table_catalog] = database.getCatalogName().originalName;
                        row[table_schema] = refName.schema.originalName;
                        row[table_name] = refName.originalName;

                        try
                        {
                            t.insertSys(store, row);
                        }
                        catch (CoreException ) { }
                    }
                }
            }

            return t;
        }

        Table ROUTINES()
        {

            Table t = sysTables[ID_ROUTINES];

            if (t == null)
            {
                t = createBlankTable(sysTableHsqlNames[ID_ROUTINES]);

                addColumn(t, "SPECIFIC_CATALOG", SQL_IDENTIFIER);
                addColumn(t, "SPECIFIC_SCHEMA", SQL_IDENTIFIER);
                addColumn(t, "SPECIFIC_NAME", SQL_IDENTIFIER);
                addColumn(t, "ROUTINE_CATALOG", SQL_IDENTIFIER);
                addColumn(t, "ROUTINE_SCHEMA", SQL_IDENTIFIER);
                addColumn(t, "ROUTINE_NAME", SQL_IDENTIFIER);
                addColumn(t, "ROUTINE_TYPE", CHARACTER_DATA);
                addColumn(t, "MODULE_CATALOG", SQL_IDENTIFIER);
                addColumn(t, "MODULE_SCHEMA", SQL_IDENTIFIER);
                addColumn(t, "MODULE_NAME", SQL_IDENTIFIER);
                addColumn(t, "UDT_CATALOG", SQL_IDENTIFIER);
                addColumn(t, "UDT_SCHEMA", SQL_IDENTIFIER);
                addColumn(t, "UDT_NAME", SQL_IDENTIFIER);
                addColumn(t, "DATA_TYPE", CHARACTER_DATA);
                addColumn(t, "CHARACTER_MAXIMUM_LENGTH", CARDINAL_NUMBER);
                addColumn(t, "CHARACTER_OCTET_LENGTH", CARDINAL_NUMBER);
                addColumn(t, "CHARACTER_SET_CATALOG", SQL_IDENTIFIER);
                addColumn(t, "CHARACTER_SET_SCHEMA", SQL_IDENTIFIER);
                addColumn(t, "CHARACTER_SET_NAME", SQL_IDENTIFIER);
                addColumn(t, "COLLATION_CATALOG", SQL_IDENTIFIER);
                addColumn(t, "COLLATION_SCHEMA", SQL_IDENTIFIER);          //
                addColumn(t, "COLLATION_NAME", SQL_IDENTIFIER);
                addColumn(t, "NUMERIC_PRECISION", CARDINAL_NUMBER);        //
                addColumn(t, "NUMERIC_PRECISION_RADIX", CARDINAL_NUMBER);
                addColumn(t, "NUMERIC_SCALE", CARDINAL_NUMBER);
                addColumn(t, "DATETIME_PRECISION", CARDINAL_NUMBER);
                addColumn(t, "INTERVAL_TYPE", CHARACTER_DATA);
                addColumn(t, "INTERVAL_PRECISION", CARDINAL_NUMBER);
                addColumn(t, "TYPE_UDT_CATALOG", SQL_IDENTIFIER);
                addColumn(t, "TYPE_UDT_SCHEMA", SQL_IDENTIFIER);
                addColumn(t, "TYPE_UDT_NAME", SQL_IDENTIFIER);
                addColumn(t, "SCOPE_CATALOG", SQL_IDENTIFIER);
                addColumn(t, "SCOPE_SCHEMA", SQL_IDENTIFIER);
                addColumn(t, "SCOPE_NAME", SQL_IDENTIFIER);                //
                addColumn(t, "MAXIMUM_CARDINALITY", CARDINAL_NUMBER);      // NULL (only for array tyes)
                addColumn(t, "DTD_IDENTIFIER", SQL_IDENTIFIER);
                addColumn(t, "ROUTINE_BODY", CHARACTER_DATA);
                addColumn(t, "ROUTINE_DEFINITION", CHARACTER_DATA);
                addColumn(t, "EXTERNAL_NAME", CHARACTER_DATA);
                addColumn(t, "EXTERNAL_LANGUAGE", CHARACTER_DATA);
                addColumn(t, "PARAMETER_STYLE", CHARACTER_DATA);
                addColumn(t, "IS_DETERMINISTIC", YES_OR_NO);
                addColumn(t, "SQL_DATA_ACCESS", CHARACTER_DATA);
                addColumn(t, "IS_NULL_CALL", YES_OR_NO);
                addColumn(t, "SQL_PATH", CHARACTER_DATA);
                addColumn(t, "SCHEMA_LEVEL_ROUTINE", YES_OR_NO);           //
                addColumn(t, "MAX_DYNAMIC_RESULT_SETS", CARDINAL_NUMBER);
                addColumn(t, "IS_USER_DEFINED_CAST", YES_OR_NO);
                addColumn(t, "IS_IMPLICITLY_INVOCABLE", YES_OR_NO);
                addColumn(t, "SECURITY_TYPE", CHARACTER_DATA);
                addColumn(t, "TO_SQL_SPECIFIC_CATALOG", SQL_IDENTIFIER);
                addColumn(t, "TO_SQL_SPECIFIC_SCHEMA", SQL_IDENTIFIER);    //
                addColumn(t, "TO_SQL_SPECIFIC_NAME", SQL_IDENTIFIER);
                addColumn(t, "AS_LOCATOR", YES_OR_NO);
                addColumn(t, "CREATED", TIME_STAMP);
                addColumn(t, "LAST_ALTERED", TIME_STAMP);
                addColumn(t, "NEW_SAVEPOINT_LEVEL", YES_OR_NO);
                addColumn(t, "IS_UDT_DEPENDENT", YES_OR_NO);
                addColumn(t, "RESULT_CAST_FROM_DATA_TYPE", CHARACTER_DATA);
                addColumn(t, "RESULT_CAST_AS_LOCATOR", YES_OR_NO);
                addColumn(t, "RESULT_CAST_CHAR_MAX_LENGTH", CARDINAL_NUMBER);
                addColumn(t, "RESULT_CAST_CHAR_OCTET_LENGTH", CARDINAL_NUMBER);
                addColumn(t, "RESULT_CAST_CHAR_SET_CATALOG", CHARACTER_DATA);
                addColumn(t, "RESULT_CAST_CHAR_SET_SCHEMA", SQL_IDENTIFIER);
                addColumn(t, "RESULT_CAST_CHARACTER_SET_NAME", SQL_IDENTIFIER);
                addColumn(t, "RESULT_CAST_COLLATION_CATALOG", SQL_IDENTIFIER);
                addColumn(t, "RESULT_CAST_COLLATION_SCHEMA", SQL_IDENTIFIER);
                addColumn(t, "RESULT_CAST_COLLATION_NAME", SQL_IDENTIFIER);
                addColumn(t, "RESULT_CAST_NUMERIC_PRECISION", CARDINAL_NUMBER);
                addColumn(t, "RESULT_CAST_NUMERIC_RADIX", CARDINAL_NUMBER);
                addColumn(t, "RESULT_CAST_NUMERIC_SCALE", CARDINAL_NUMBER);
                addColumn(t, "RESULT_CAST_DATETIME_PRECISION", CARDINAL_NUMBER);
                addColumn(t, "RESULT_CAST_INTERVAL_TYPE", CHARACTER_DATA);
                addColumn(t, "RESULT_CAST_INTERVAL_PRECISION", CARDINAL_NUMBER);
                addColumn(t, "RESULT_CAST_TYPE_UDT_CATALOG", SQL_IDENTIFIER);
                addColumn(t, "RESULT_CAST_TYPE_UDT_SCHEMA", SQL_IDENTIFIER);
                addColumn(t, "RESULT_CAST_TYPE_UDT_NAME", SQL_IDENTIFIER);
                addColumn(t, "RESULT_CAST_SCOPE_CATALOG", SQL_IDENTIFIER);
                addColumn(t, "RESULT_CAST_SCOPE_SCHEMA", SQL_IDENTIFIER);
                addColumn(t, "RESULT_CAST_SCOPE_NAME", SQL_IDENTIFIER);
                addColumn(t, "RESULT_CAST_MAX_CARDINALITY", CARDINAL_NUMBER);
                addColumn(t, "RESULT_CAST_DTD_IDENTIFIER", CHARACTER_DATA);
                addColumn(t, "DECLARED_DATA_TYPE", CHARACTER_DATA);
                addColumn(t, "DECLARED_NUMERIC_PRECISION", CARDINAL_NUMBER);
                addColumn(t, "DECLARED_NUMERIC_SCALE", CARDINAL_NUMBER);
                addColumn(t, "RESULT_CAST_FROM_DECLARED_DATA_TYPE",
                          CHARACTER_DATA);
                addColumn(t, "RESULT_CAST_DECLARED_NUMERIC_PRECISION",
                          CARDINAL_NUMBER);
                addColumn(t, "RESULT_CAST_DECLARED_NUMERIC_SCALE",
                          CARDINAL_NUMBER);

                QNameManager.QName name = QNameManager.newInfoSchemaObjectName(
                    sysTableHsqlNames[ID_ROUTINES].name, false, SchemaObjectTypes.INDEX);

                t.createPrimaryKey(name, new int[] {
                3, 4, 5, 0, 1, 2
            }, false);

                return t;
            }

            // column number mappings
            int specific_catalog = 0;
            int specific_schema = 1;
            int specific_name = 2;
            int routine_catalog = 3;
            int routine_schema = 4;
            int routine_name = 5;
            int routine_type = 6;
            int module_catalog = 7;
            int module_schema = 8;
            int module_name = 9;
            int udt_catalog = 10;
            int udt_schema = 11;
            int udt_name = 12;
            int data_type = 13;
            int character_maximum_length = 14;
            int character_octet_length = 15;
            int character_set_catalog = 16;
            int character_set_schema = 17;
            int character_set_name = 18;
            int collation_catalog = 19;
            int collation_schema = 20;
            int collation_name = 21;
            int numeric_precision = 22;
            int numeric_precision_radix = 23;
            int numeric_scale = 24;
            int datetime_precision = 25;
            int interval_type = 26;
            int interval_precision = 27;
            int type_udt_catalog = 28;
            int type_udt_schema = 29;
            int type_udt_name = 30;
            int scope_catalog = 31;
            int scope_schema = 32;
            int scope_name = 33;
            int maximum_cardinality = 34;
            int dtd_identifier = 35;
            int routine_body = 36;
            int routine_definition = 37;
            int external_name = 38;
            int external_language = 39;
            int parameter_style = 40;
            int is_deterministic = 41;
            int sql_data_access = 42;
            int is_null_call = 43;
            int sql_path = 44;
            int schema_level_routine = 45;
            int max_dynamic_result_sets = 46;
            int is_user_defined_cast = 47;
            int is_implicitly_invocable = 48;
            int security_type = 49;
            int to_sql_specific_catalog = 50;
            int to_sql_specific_schema = 51;
            int to_sql_specific_name = 52;
            int as_locator = 53;
            int created = 54;
            int last_altered = 55;
            int new_savepoint_level = 56;
            int is_udt_dependent = 57;
            int result_cast_from_data_type = 58;
            int result_cast_as_locator = 59;
            int result_cast_char_max_length = 60;
            int result_cast_char_octet_length = 61;
            int result_cast_char_set_catalog = 62;
            int result_cast_char_set_schema = 63;
            int result_cast_character_set_name = 64;
            int result_cast_collation_catalog = 65;
            int result_cast_collation_schema = 66;
            int result_cast_collation_name = 67;
            int result_cast_numeric_precision = 68;
            int result_cast_numeric_radix = 69;
            int result_cast_numeric_scale = 70;
            int result_cast_datetime_precision = 71;
            int result_cast_interval_type = 72;
            int result_cast_interval_precision = 73;
            int result_cast_type_udt_catalog = 74;
            int result_cast_type_udt_schema = 75;
            int result_cast_type_udt_name = 76;
            int result_cast_scope_catalog = 77;
            int result_cast_scope_schema = 78;
            int result_cast_scope_name = 79;
            int result_cast_max_cardinality = 80;
            int result_cast_dtd_identifier = 81;
            int declared_data_type = 82;
            int declared_numeric_precision = 83;
            int declared_numeric_scale = 84;
            int result_cast_from_declared_data_type = 85;
            int result_cast_declared_numeric_precision = 86;
            int result_cast_declared_numeric_scale = 87;

            //
            PersistentStore store = database.persistentStoreCollection.getStore(t);
            Iterator it;
            Object[] row;

            it = database.schemaManager.databaseObjectIterator(
                SchemaObjectTypes.ROUTINE);

            while (it.hasNext())
            {
                RoutineSchema routine = (RoutineSchema)it.next();

                if (!session.getGrantee().isAccessible(routine))
                {
                    continue;
                }

                Routine[] specifics = routine.getSpecificRoutines();

                for (int m = 0; m < specifics.Length; m++)
                {
                    row = t.getEmptyRowData();

                    Routine specific = specifics[m];
                    SqlType type = specific.isProcedure() ? null
                                                              : specific
                                                                  .getReturnType();

                    //
                    row[specific_catalog] = database.getCatalogName().originalName;
                    row[specific_schema] = specific.getSchemaName().originalName;
                    row[specific_name] = specific.getSpecificName().originalName;
                    row[routine_catalog] = database.getCatalogName().originalName;
                    row[routine_schema] = routine.getSchemaName().originalName;
                    row[routine_name] = specific.getName().originalName;
                    row[routine_type] = specific.isProcedure() ? Tokens.T_PROCEDURE
                                                               : Tokens.T_FUNCTION;
                    row[module_catalog] = null;
                    row[module_schema] = null;
                    row[module_name] = null;
                    row[udt_catalog] = null;
                    row[udt_schema] = null;
                    row[udt_name] = null;
                    row[data_type] = type == null ? null
                                                       : type.getNameString();

                    if (type != null)
                    {

                        // common type block
                        if (type.isCharacterType())
                        {
                            row[character_maximum_length] =
                                (long)(type.precision);
                            row[character_octet_length] =
                                (long)(type.precision * 2);
                            row[character_set_catalog] =
                                database.getCatalogName().originalName;
                            row[character_set_schema] =
                                ((CharacterType)type).getCharacterSet()
                                    .getSchemaName().originalName;
                            row[character_set_name] =
                                ((CharacterType)type).getCharacterSet().getName()
                                    .originalName;
                            row[collation_catalog] =
                                database.getCatalogName().originalName;
                            row[collation_schema] =
                                ((CharacterType)type).getCollation()
                                    .getSchemaName().originalName;
                            row[collation_name] =
                                ((CharacterType)type).getCollation().getName()
                                    .originalName;
                        }
                        else if (type.isNumberType())
                        {
                            row[numeric_precision] = (long)(
                                ((NumberType)type).getNumericPrecisionInRadix());
                            row[declared_numeric_precision] = (long)(
                                ((NumberType)type).getNumericPrecisionInRadix());

                            if (type.isExactNumberType())
                            {
                                row[numeric_scale] = row[declared_numeric_scale] =
                                    (long)(type.scale);
                            }

                            row[numeric_precision_radix] =
                                (long)(type.getPrecisionRadix());
                        }
                        else if (type.isBooleanType()) { }
                        else if (type.isDateTimeType())
                        {
                            row[datetime_precision] =
                                (long)(type.scale);
                        }
                        else if (type.isIntervalType())
                        {
                            row[data_type] = "INTERVAL";
                            row[interval_type] =
                                IntervalType.getQualifier(type.typeCode);
                            row[interval_precision] =
                                (long)(type.precision);
                            row[datetime_precision] =
                                (long)(type.scale);
                        }
                        else if (type.isBinaryType())
                        {
                            row[character_maximum_length] =
                                (long)(type.precision);
                            row[character_octet_length] =
                                (long)(type.precision);
                        }
                        else if (type.isBitType())
                        {
                            row[character_maximum_length] =
                                (long)(type.precision);
                            row[character_octet_length] =
                                (long)(type.precision);
                        }

                        // end common block
                    }

                    row[type_udt_catalog] = null;
                    row[type_udt_schema] = null;
                    row[type_udt_name] = null;
                    row[scope_catalog] = null;
                    row[scope_schema] = null;
                    row[scope_name] = null;
                    row[maximum_cardinality] = null;
                    row[dtd_identifier] = null;    //**
                    row[routine_body] = specific.getLanguage()
                                        == Routine.LANGUAGE_JAVA ? "EXTERNAL"
                                                                 : "SQL";
                    row[routine_definition] = specific.getSQL();
                    row[external_name] =
                        specific.getLanguage() == Routine.LANGUAGE_JAVA
                        ? specific.getMethod().Name
                        : null;
                    row[external_language] = specific.getLanguage()
                                             == Routine.LANGUAGE_JAVA ? "JAVA"
                                                                      : null;
                    row[parameter_style] = specific.getLanguage()
                                           == Routine.LANGUAGE_JAVA ? "JAVA"
                                                                    : null;
                    row[is_deterministic] = specific.isDeterministic() ? "YES"
                                                                       : "NO";
                    row[sql_data_access] = specific.getDataImpactString();
                    row[is_null_call] = type == null ? null
                                                         : specific.isNullInputOutput()
                                                           ? "YES"
                                                           : "NO";
                    row[sql_path] = null;
                    row[schema_level_routine] = "YES";
                    row[max_dynamic_result_sets] = (long)(0);
                    row[is_user_defined_cast] = type == null ? null
                                                             : "NO";
                    row[is_implicitly_invocable] = null;
                    row[security_type] = "DEFINER";
                    row[to_sql_specific_catalog] = null;
                    row[to_sql_specific_schema] = null;
                    row[to_sql_specific_name] = null;
                    row[as_locator] = type == null ? null
                                                   : "NO";
                    row[created] = null;
                    row[last_altered] = null;
                    row[new_savepoint_level] = "YES";
                    row[is_udt_dependent] = null;
                    row[result_cast_from_data_type] = null;
                    row[result_cast_as_locator] = null;
                    row[result_cast_char_max_length] = null;
                    row[result_cast_char_octet_length] = null;
                    row[result_cast_char_set_catalog] = null;
                    row[result_cast_char_set_schema] = null;
                    row[result_cast_character_set_name] = null;
                    row[result_cast_collation_catalog] = null;
                    row[result_cast_collation_schema] = null;
                    row[result_cast_collation_name] = null;
                    row[result_cast_numeric_precision] = null;
                    row[result_cast_numeric_radix] = null;
                    row[result_cast_numeric_scale] = null;
                    row[result_cast_datetime_precision] = null;
                    row[result_cast_interval_type] = null;
                    row[result_cast_interval_precision] = null;
                    row[result_cast_type_udt_catalog] = null;
                    row[result_cast_type_udt_schema] = null;
                    row[result_cast_type_udt_name] = null;
                    row[result_cast_scope_catalog] = null;
                    row[result_cast_scope_schema] = null;
                    row[result_cast_scope_name] = null;
                    row[result_cast_max_cardinality] = null;
                    row[result_cast_dtd_identifier] = null;
                    row[declared_data_type] = row[data_type];
                    row[declared_numeric_precision] = row[numeric_precision];
                    row[declared_numeric_scale] = row[numeric_scale];
                    row[result_cast_from_declared_data_type] = null;
                    row[result_cast_declared_numeric_precision] = null;
                    row[result_cast_declared_numeric_scale] = null;

                    t.insertSys(store, row);
                }
            }

            return t;
        }

        /**
         * SCHEMATA<p>
         *
         * <b>Function</b><p>
         *
         * The SCHEMATA view has one row for each accessible schema. <p>
         *
         * <b>Definition</b><p>
         *
         * <pre class="SqlCodeExample">
         * CREATE TABLE SCHEMATA (
         *      CATALOG_NAME INFORMATION_SCHEMA.SQL_IDENTIFIER,
         *      SCHEMA_NAME INFORMATION_SCHEMA.SQL_IDENTIFIER,
         *      SCHEMA_OWNER INFORMATION_SCHEMA.SQL_IDENTIFIER
         *          CONSTRAINT SCHEMA_OWNER_NOT_NULL
         *              NOT NULL,
         *      DEFAULT_CHARACTER_SET_CATALOG INFORMATION_SCHEMA.SQL_IDENTIFIER
         *          CONSTRAINT DEFAULT_CHARACTER_SET_CATALOG_NOT_NULL
         *              NOT NULL,
         *      DEFAULT_CHARACTER_SET_SCHEMA INFORMATION_SCHEMA.SQL_IDENTIFIER
         *          CONSTRAINT DEFAULT_CHARACTER_SET_SCHEMA_NOT_NULL
         *              NOT NULL,
         *      DEFAULT_CHARACTER_SET_NAME INFORMATION_SCHEMA.SQL_IDENTIFIER
         *          CONSTRAINT DEFAULT_CHARACTER_SET_NAME_NOT_NULL
         *              NOT NULL,
         *      SQL_PATH INFORMATION_SCHEMA.CHARACTER_DATA,
         *
         *      CONSTRAINT SCHEMATA_PRIMARY_KEY
         *          PRIMARY KEY ( CATALOG_NAME, SCHEMA_NAME ),
         *      CONSTRAINT SCHEMATA_FOREIGN_KEY_AUTHORIZATIONS
         *          FOREIGN KEY ( SCHEMA_OWNER )
         *              REFERENCES AUTHORIZATIONS,
         *      CONSTRAINT SCHEMATA_FOREIGN_KEY_CATALOG_NAMES
         *          FOREIGN KEY ( CATALOG_NAME )
         *              REFERENCES CATALOG_NAMES
         *      )
         * </pre>
         *
         * <b>Description</b><p>
         *
         * <ol>
         *      <li>The value of CATALOG_NAME is the name of the catalog of the
         *          schema described by this row.<p>
         *
         *      <li>The value of SCHEMA_NAME is the unqualified schema name of
         *          the schema described by this row.<p>
         *
         *      <li>The values of SCHEMA_OWNER are the authorization identifiers
         *          that own the schemata.<p>
         *
         *      <li>The values of DEFAULT_CHARACTER_SET_CATALOG,
         *          DEFAULT_CHARACTER_SET_SCHEMA, and DEFAULT_CHARACTER_SET_NAME
         *          are the catalog name, unqualified schema name, and qualified
         *          identifier, respectively, of the default character set for
         *          columns and domains in the schemata.<p>
         *
         *      <li>Case:<p>
         *          <ul>
         *              <li>If &lt;schema path specification&gt; was specified in
         *                  the &lt;schema definition&gt; that defined the schema
         *                  described by this row and the character representation
         *                  of the &lt;schema path specification&gt; can be
         *                  represented without truncation, then the value of
         *                  SQL_PATH is that character representation.<p>
         *
         *              <li>Otherwise, the value of SQL_PATH is the null value.
         *         </ul>
         * </ol>
         *
         * @return Table
         */
        Table SCHEMATA()
        {

            Table t = sysTables[ID_SCHEMATA];

            if (t == null)
            {
                t = createBlankTable(sysTableHsqlNames[ID_SCHEMATA]);

                addColumn(t, "CATALOG_NAME", SQL_IDENTIFIER);
                addColumn(t, "SCHEMA_NAME", SQL_IDENTIFIER);
                addColumn(t, "SCHEMA_OWNER", SQL_IDENTIFIER);
                addColumn(t, "DEFAULT_CHARACTER_SET_CATALOG", SQL_IDENTIFIER);
                addColumn(t, "DEFAULT_CHARACTER_SET_SCHEMA", SQL_IDENTIFIER);
                addColumn(t, "DEFAULT_CHARACTER_SET_NAME", SQL_IDENTIFIER);
                addColumn(t, "SQL_PATH", CHARACTER_DATA);

                // order: CATALOG_NAME, SCHEMA_NAME
                // false PK, as rows may have NULL CATALOG_NAME
                QNameManager.QName name = QNameManager.newInfoSchemaObjectName(
                    sysTableHsqlNames[ID_SCHEMATA].name, false, SchemaObjectTypes.INDEX);

                t.createPrimaryKey(name, new int[] {
                0, 1
            }, false);

                return t;
            }

            PersistentStore store = database.persistentStoreCollection.getStore(t);

            // Intermediate holders
            Iterator schemas;
            String schema;
            String dcsSchema = SqlInvariants.INFORMATION_SCHEMA;
            String dcsName = ("UTF16");
            String sqlPath = null;
            Grantee user = session.getGrantee();
            Object[] row;

            // column number mappings
            int schema_catalog = 0;
            int schema_name = 1;
            int schema_owner = 2;
            int default_character_set_catalog = 3;
            int default_character_set_schema = 4;
            int default_character_set_name = 5;
            int sql_path = 6;

            // Initialization
            schemas = database.schemaManager.fullSchemaNamesIterator();

            // Do it.
            while (schemas.hasNext())
            {
                schema = (String)schemas.next();
                QNameManager.QName schemaHsqlName = database.schemaManager.getSchemaHsqlName(schema);

                if (!user.hasSchemaUpdateOrGrantRights(schema))
                {
                    continue;
                }

                row = t.getEmptyRowData();
                row[schema_catalog] = database.getCatalogName().originalName;
                row[schema_name] = schemaHsqlName.originalName;
                row[schema_owner] =
                    database.schemaManager.toSchemaOwner(schema).getOriginalNameString();
                row[default_character_set_catalog] =
                    database.getCatalogName().originalName;
                row[default_character_set_schema] = dcsSchema;
                row[default_character_set_name] = dcsName;
                row[sql_path] = sqlPath;

                t.insertSys(store, row);
            }

            return t;
        }

        Table SQL_FEATURES()
        {

            Table t = sysTables[ID_SQL_FEATURES];

            if (t == null)
            {
                t = createBlankTable(sysTableHsqlNames[ID_SQL_FEATURES]);

                addColumn(t, "FEATURE_ID", CHARACTER_DATA);
                addColumn(t, "FEATURE_NAME", CHARACTER_DATA);
                addColumn(t, "SUB_FEATURE_ID", CHARACTER_DATA);
                addColumn(t, "SUB_FEATURE_NAME", CHARACTER_DATA);
                addColumn(t, "IS_SUPPORTED", YES_OR_NO);
                addColumn(t, "IS_VERIFIED_BY", CHARACTER_DATA);
                addColumn(t, "COMMENTS", CHARACTER_DATA);

                QNameManager.QName name = QNameManager.newInfoSchemaObjectName(
                    sysTableHsqlNames[ID_SQL_FEATURES].name, false,
                    SchemaObjectTypes.INDEX);

                t.createPrimaryKey(name, new int[] {
                0, 2
            }, false);

                return t;
            }

            PersistentStore store = database.persistentStoreCollection.getStore(t);
            Session sys = database.sessionManager.newSysSession(
                SqlInvariants.INFORMATION_SCHEMA_QNAME, session.getUser());
            String sql = (String)statementMap.get("/*sql_features*/");
            Result rs = sys.executeDirectStatement(sql);

            t.insertSys(store, rs);

            return t;
        }

        Table SQL_IMPLEMENTATION_INFO()
        {

            Table t = sysTables[ID_SQL_IMPLEMENTATION_INFO];

            if (t == null)
            {
                t = createBlankTable(sysTableHsqlNames[ID_SQL_IMPLEMENTATION_INFO]);

                addColumn(t, "IMPLEMENTATION_INFO_ID", CHARACTER_DATA);
                addColumn(t, "IMPLEMENTATION_INFO_NAME", CHARACTER_DATA);
                addColumn(t, "INTEGER_VALUE", CARDINAL_NUMBER);
                addColumn(t, "CHARACTER_VALUE", CHARACTER_DATA);
                addColumn(t, "COMMENTS", CHARACTER_DATA);

                QNameManager.QName name = QNameManager.newInfoSchemaObjectName(
                    sysTableHsqlNames[ID_SQL_IMPLEMENTATION_INFO].name, false,
                    SchemaObjectTypes.INDEX);

                t.createPrimaryKey(name, new int[] { 0 }, false);

                return t;
            }

            PersistentStore store = database.persistentStoreCollection.getStore(t);
            Session sys = database.sessionManager.newSysSession(
                SqlInvariants.INFORMATION_SCHEMA_QNAME, session.getUser());

            /*
                    Result rs = sys.executeDirectStatement(
                        "VALUES "
                        + ";");

                    t.insertSys(store, rs);
            */
            return t;
        }

        Table SQL_PACKAGES()
        {

            Table t = sysTables[ID_SQL_PACKAGES];

            if (t == null)
            {
                t = createBlankTable(sysTableHsqlNames[ID_SQL_PACKAGES]);

                addColumn(t, "ID", CHARACTER_DATA);
                addColumn(t, "NAME", CHARACTER_DATA);
                addColumn(t, "IS_SUPPORTED", YES_OR_NO);
                addColumn(t, "IS_VERIFIED_BY", CHARACTER_DATA);
                addColumn(t, "COMMENTS", CHARACTER_DATA);

                QNameManager.QName name = QNameManager.newInfoSchemaObjectName(
                    sysTableHsqlNames[ID_SQL_PACKAGES].name, false,
                    SchemaObjectTypes.INDEX);

                t.createPrimaryKey(name, new int[] { 0 }, false);

                return t;
            }

            PersistentStore store = database.persistentStoreCollection.getStore(t);
            Session sys = database.sessionManager.newSysSession(
                SqlInvariants.INFORMATION_SCHEMA_QNAME, session.getUser());
            String sql = (String)statementMap.get("/*sql_packages*/");
            Result rs = sys.executeDirectStatement(sql);

            t.insertSys(store, rs);

            return t;
        }

        Table SQL_PARTS()
        {

            Table t = sysTables[ID_SQL_PARTS];

            if (t == null)
            {
                t = createBlankTable(sysTableHsqlNames[ID_SQL_PARTS]);

                addColumn(t, "PART", CHARACTER_DATA);
                addColumn(t, "NAME", CHARACTER_DATA);
                addColumn(t, "IS_SUPPORTED", YES_OR_NO);
                addColumn(t, "IS_VERIFIED_BY", CHARACTER_DATA);
                addColumn(t, "COMMENTS", CHARACTER_DATA);

                QNameManager.QName name = QNameManager.newInfoSchemaObjectName(
                    sysTableHsqlNames[ID_SQL_PARTS].name, false, SchemaObjectTypes.INDEX);

                t.createPrimaryKey(name, new int[] { 0 }, false);

                return t;
            }

            PersistentStore store = database.persistentStoreCollection.getStore(t);
            Session sys = database.sessionManager.newSysSession(
                SqlInvariants.INFORMATION_SCHEMA_QNAME, session.getUser());
            String sql = (String)statementMap.get("/*sql_parts*/");
            Result rs = sys.executeDirectStatement(sql);

            t.insertSys(store, rs);

            return t;
        }

        Table SQL_SIZING()
        {

            Table t = sysTables[ID_SQL_SIZING];

            if (t == null)
            {
                t = createBlankTable(sysTableHsqlNames[ID_SQL_SIZING]);

                addColumn(t, "SIZING_ID", CARDINAL_NUMBER);
                addColumn(t, "SIZING_NAME", CHARACTER_DATA);
                addColumn(t, "SUPPORTED_VALUE", CARDINAL_NUMBER);
                addColumn(t, "COMMENTS", CHARACTER_DATA);

                QNameManager.QName name = QNameManager.newInfoSchemaObjectName(
                    sysTableHsqlNames[ID_SQL_SIZING].name, false, SchemaObjectTypes.INDEX);

                t.createPrimaryKey(name, new int[] { 0 }, false);

                return t;
            }

            PersistentStore store = database.persistentStoreCollection.getStore(t);
            Session sys = database.sessionManager.newSysSession(
                SqlInvariants.INFORMATION_SCHEMA_QNAME, session.getUser());
            String sql = (String)statementMap.get("/*sql_sizing*/");
            Result rs = sys.executeDirectStatement(sql);

            t.insertSys(store, rs);

            return t;
        }

        Table SQL_SIZING_PROFILES()
        {

            Table t = sysTables[ID_SQL_SIZING_PROFILES];

            if (t == null)
            {
                t = createBlankTable(sysTableHsqlNames[ID_SQL_SIZING_PROFILES]);

                addColumn(t, "SIZING_ID", CARDINAL_NUMBER);
                addColumn(t, "SIZING_NAME", CHARACTER_DATA);
                addColumn(t, "PROFILE_ID", CARDINAL_NUMBER);
                addColumn(t, "PROFILE_NAME", CHARACTER_DATA);
                addColumn(t, "REQUIRED_VALUE", CARDINAL_NUMBER);
                addColumn(t, "COMMENTS", CHARACTER_DATA);

                QNameManager.QName name = QNameManager.newInfoSchemaObjectName(
                    sysTableHsqlNames[ID_SQL_SIZING_PROFILES].name, false,
                    SchemaObjectTypes.INDEX);

                t.createPrimaryKey(name, new int[] { 0 }, false);

                return t;
            }

            PersistentStore store = database.persistentStoreCollection.getStore(t);
            Session sys = database.sessionManager.newSysSession(
                SqlInvariants.INFORMATION_SCHEMA_QNAME, session.getUser());

            /*
                    Result rs = sys.executeDirectStatement(
                        "VALUES "
                        + ";");

                    t.insertSys(store, rs);
            */
            return t;
        }

        /**
         * The TABLE_CONSTRAINTS table has one row for each table constraint
         * associated with a table.  <p>
         *
         * It effectively contains a representation of the table constraint
         * descriptors. <p>
         *
         * <b>Definition:</b> <p>
         *
         * <pre class="SqlCodeExample">
         * CREATE TABLE SYSTEM_TABLE_CONSTRAINTS (
         *      CONSTRAINT_CATALOG      VARCHAR NULL,
         *      CONSTRAINT_SCHEMA       VARCHAR NULL,
         *      CONSTRAINT_NAME         VARCHAR NOT NULL,
         *      CONSTRAINT_TYPE         VARCHAR NOT NULL,
         *      TABLE_CATALOG           VARCHAR NULL,
         *      TABLE_SCHEMA            VARCHAR NULL,
         *      TABLE_NAME              VARCHAR NOT NULL,
         *      IS_DEFERRABLE           VARCHAR NOT NULL,
         *      INITIALLY_DEFERRED      VARCHAR NOT NULL,
         *
         *      CHECK ( CONSTRAINT_TYPE IN
         *                      ( 'UNIQUE', 'PRIMARY KEY',
         *                        'FOREIGN KEY', 'CHECK' ) ),
         *
         *      CHECK ( ( IS_DEFERRABLE, INITIALLY_DEFERRED ) IN
         *              ( VALUES ( 'NO',  'NO'  ),
         *                       ( 'YES', 'NO'  ),
         *                       ( 'YES', 'YES' ) ) )
         * )
         * </pre>
         *
         * <b>Description:</b> <p>
         *
         * <ol>
         * <li> The values of CONSTRAINT_CATALOG, CONSTRAINT_SCHEMA, and
         *      CONSTRAINT_NAME are the catalog name, unqualified schema
         *      name, and qualified identifier, respectively, of the
         *      constraint being described. If the &lt;table constraint
         *      definition&gt; or &lt;add table constraint definition&gt;
         *      that defined the constraint did not specify a
         *      &lt;constraint name&gt;, then the values of CONSTRAINT_CATALOG,
         *      CONSTRAINT_SCHEMA, and CONSTRAINT_NAME are
         *      implementation-defined. <p>
         *
         * <li> The values of CONSTRAINT_TYPE have the following meanings: <p>
         *  <table border cellpadding="3">
         *  <tr>
         *      <td nowrap>FOREIGN KEY</td>
         *      <td nowrap>The constraint being described is a
         *                 foreign key constraint.</td>
         *  </tr>
         *  <tr>
         *      <td nowrap>UNIQUE</td>
         *      <td nowrap>The constraint being described is a
         *                 unique constraint.</td>
         *  </tr>
         *  <tr>
         *      <td nowrap>PRIMARY KEY</td>
         *      <td nowrap>The constraint being described is a
         *                 primary key constraint.</td>
         *  </tr>
         *  <tr>
         *      <td nowrap>CHECK</td>
         *      <td nowrap>The constraint being described is a
         *                 check constraint.</td>
         *  </tr>
         * </table> <p>
         *
         * <li> The values of TABLE_CATALOG, TABLE_SCHEMA, and TABLE_NAME are
         *      the catalog name, the unqualified schema name, and the
         *      qualified identifier of the name of the table to which the
         *      table constraint being described applies. <p>
         *
         * <li> The values of IS_DEFERRABLE have the following meanings: <p>
         *
         *  <table>
         *      <tr>
         *          <td nowrap>YES</td>
         *          <td nowrap>The table constraint is deferrable.</td>
         *      </tr>
         *      <tr>
         *          <td nowrap>NO</td>
         *          <td nowrap>The table constraint is not deferrable.</td>
         *      </tr>
         *  </table> <p>
         *
         * <li> The values of INITIALLY_DEFERRED have the following meanings: <p>
         *
         *  <table>
         *      <tr>
         *          <td nowrap>YES</td>
         *          <td nowrap>The table constraint is initially deferred.</td>
         *      </tr>
         *      <tr>
         *          <td nowrap>NO</td>
         *          <td nowrap>The table constraint is initially immediate.</td>
         *      </tr>
         *  </table> <p>
         * </ol>
         *
         * @return Table
         */
        Table TABLE_CONSTRAINTS()
        {

            Table t = sysTables[ID_TABLE_CONSTRAINTS];

            if (t == null)
            {
                t = createBlankTable(sysTableHsqlNames[ID_TABLE_CONSTRAINTS]);

                addColumn(t, "CONSTRAINT_CATALOG", SQL_IDENTIFIER);
                addColumn(t, "CONSTRAINT_SCHEMA", SQL_IDENTIFIER);
                addColumn(t, "CONSTRAINT_NAME", SQL_IDENTIFIER);    // not null
                addColumn(t, "CONSTRAINT_TYPE", CHARACTER_DATA);    // not null
                addColumn(t, "TABLE_CATALOG", SQL_IDENTIFIER);
                addColumn(t, "TABLE_SCHEMA", SQL_IDENTIFIER);
                addColumn(t, "TABLE_NAME", SQL_IDENTIFIER);         // not null
                addColumn(t, "IS_DEFERRABLE", YES_OR_NO);           // not null
                addColumn(t, "INITIALLY_DEFERRED", YES_OR_NO);      // not null

                // false PK, as CONSTRAINT_CATALOG, CONSTRAINT_SCHEMA,
                // TABLE_CATALOG and/or TABLE_SCHEMA may be null
                QNameManager.QName name = QNameManager.newInfoSchemaObjectName(
                    sysTableHsqlNames[ID_TABLE_CONSTRAINTS].name, false,
                    SchemaObjectTypes.INDEX);

                t.createPrimaryKey(name, new int[] {
                0, 1, 2, 4, 5, 6
            }, false);

                return t;
            }

            PersistentStore store = database.persistentStoreCollection.getStore(t);

            // Intermediate holders
            Iterator tables;
            Table table;
            Constraint[] constraints;
            int constraintCount;
            Constraint constraint;
            String cat;
            String schem;
            Object[] row;

            // column number mappings
            int constraint_catalog = 0;
            int constraint_schema = 1;
            int constraint_name = 2;
            int constraint_type = 3;
            int table_catalog = 4;
            int table_schema = 5;
            int table_name = 6;
            int is_deferable = 7;
            int initially_deferred = 8;

            // initialization
            tables =
                database.schemaManager.databaseObjectIterator(SchemaObjectTypes.TABLE);
            table = null;    // else compiler complains

            // do it
            while (tables.hasNext())
            {
                table = (Table)tables.next();

                /** @todo - requires table level INSERT or UPDATE or DELETE or REFERENCES (not SELECT) right */
                if (table.isView() || !isAccessibleTable(table))
                {
                    continue;
                }

                constraints = table.getConstraints();
                constraintCount = constraints.Length;

                for (int i = 0; i < constraintCount; i++)
                {
                    constraint = constraints[i];
                    row = t.getEmptyRowData();

                    switch (constraint.getConstraintType())
                    {

                        case SchemaObjectConstraintTypes.CHECK:
                            {
                                row[constraint_type] = "CHECK";

                                break;
                            }
                        case SchemaObjectConstraintTypes.UNIQUE:
                            {
                                row[constraint_type] = "UNIQUE";

                                break;
                            }
                        case SchemaObjectConstraintTypes.FOREIGN_KEY:
                            {
                                row[constraint_type] = "FOREIGN KEY";
                                table = constraint.getRef();

                                break;
                            }
                        case SchemaObjectConstraintTypes.PRIMARY_KEY:
                            {
                                row[constraint_type] = "PRIMARY KEY";

                                break;
                            }
                        case SchemaObjectConstraintTypes.MAIN:
                        default:
                            {
                                continue;
                            }
                    }

                    cat = database.getCatalogName().originalName;
                    schem = table.getSchemaName().originalName;
                    row[constraint_catalog] = cat;
                    row[constraint_schema] = schem;
                    row[constraint_name] = constraint.getName().originalName;
                    row[table_catalog] = cat;
                    row[table_schema] = schem;
                    row[table_name] = table.getName().originalName;
                    row[is_deferable] = Tokens.T_NO;
                    row[initially_deferred] = Tokens.T_NO;

                    t.insertSys(store, row);
                }
            }

            return t;
        }

        Table TRANSLATIONS()
        {

            Table t = sysTables[ID_TRANSLATIONS];

            if (t == null)
            {
                t = createBlankTable(sysTableHsqlNames[ID_TRANSLATIONS]);

                addColumn(t, "TRANSLATION_CATALOG", SQL_IDENTIFIER);
                addColumn(t, "TRANSLATION_SCHEMA", SQL_IDENTIFIER);
                addColumn(t, "TRANSLATION_NAME", SQL_IDENTIFIER);
                addColumn(t, "SOURCE_CHARACTER_SET_CATALOG", SQL_IDENTIFIER);
                addColumn(t, "SOURCE_CHARACTER_SET_SCHEMA", SQL_IDENTIFIER);
                addColumn(t, "SOURCE_CHARACTER_SET_NAME", SQL_IDENTIFIER);
                addColumn(t, "TARGET_CHARACTER_SET_CATALOG", SQL_IDENTIFIER);
                addColumn(t, "TARGET_CHARACTER_SET_SCHEMA", SQL_IDENTIFIER);
                addColumn(t, "TARGET_CHARACTER_SET_NAME", SQL_IDENTIFIER);
                addColumn(t, "TRANSLATION_SOURCE_CATALOG", SQL_IDENTIFIER);
                addColumn(t, "TRANSLATION_SOURCE_SCHEMA", SQL_IDENTIFIER);
                addColumn(t, "TRANSLATION_SOURCE_NAME", SQL_IDENTIFIER);

                QNameManager.QName name = QNameManager.newInfoSchemaObjectName(
                    sysTableHsqlNames[ID_TRANSLATIONS].name, false,
                    SchemaObjectTypes.INDEX);

                t.createPrimaryKey(name, new int[] {
                0, 1, 2
            }, false);

                return t;
            }

            return t;
        }

        Table TRIGGER_COLUMN_USAGE()
        {

            Table t = sysTables[ID_TRIGGER_COLUMN_USAGE];

            if (t == null)
            {
                t = createBlankTable(sysTableHsqlNames[ID_TRIGGER_COLUMN_USAGE]);

                addColumn(t, "TRIGGER_CATALOG", SQL_IDENTIFIER);
                addColumn(t, "TRIGGER_SCHEMA", SQL_IDENTIFIER);
                addColumn(t, "TRIGGER_NAME", SQL_IDENTIFIER);    // not null
                addColumn(t, "TABLE_CATALOG", SQL_IDENTIFIER);
                addColumn(t, "TABLE_SCHEMA", SQL_IDENTIFIER);
                addColumn(t, "TABLE_NAME", SQL_IDENTIFIER);      // not null
                addColumn(t, "COLUMN_NAME", SQL_IDENTIFIER);     // not null

                QNameManager.QName name = QNameManager.newInfoSchemaObjectName(
                    sysTableHsqlNames[ID_TRIGGER_COLUMN_USAGE].name, false,
                    SchemaObjectTypes.INDEX);

                t.createPrimaryKey(name, new int[] {
                0, 1, 2, 3, 4, 5, 6
            }, false);

                return t;
            }

            PersistentStore store = database.persistentStoreCollection.getStore(t);

            // column number mappings
            int trigger_catalog = 0;
            int trigger_schema = 1;
            int trigger_name = 2;
            int table_catalog = 3;
            int table_schema = 4;
            int table_name = 5;
            int column_name = 6;
            Iterator it;
            Object[] row;

            it = database.schemaManager.databaseObjectIterator(
                SchemaObjectTypes.TRIGGER);

            while (it.hasNext())
            {
                TriggerDef trigger = (TriggerDef)it.next();

                if (!session.getGrantee().isAccessible(trigger))
                {
                    continue;
                }

                OrderedHashSet set = trigger.getReferences();

                for (int i = 0; i < set.size(); i++)
                {
                    QNameManager.QName refName = (QNameManager.QName)set.get(i);

                    if (refName.type != SchemaObjectTypes.COLUMN)
                    {
                        continue;
                    }

                    if (!session.getGrantee().isAccessible(refName))
                    {
                        continue;
                    }

                    row = t.getEmptyRowData();

                    //
                    row[trigger_catalog] = database.getCatalogName().originalName;
                    row[trigger_schema] = trigger.getSchemaName().originalName;
                    row[trigger_name] = trigger.getName().originalName;
                    row[table_catalog] = database.getCatalogName().originalName;
                    row[table_schema] = refName.parent.schema.originalName;
                    row[table_name] = refName.parent.originalName;
                    row[column_name] = refName.originalName;

                    try
                    {
                        t.insertSys(store, row);
                    }
                    catch (CoreException ) { }
                }
            }

            // Initialization
            return t;
        }

        Table TRIGGER_ROUTINE_USAGE()
        {

            Table t = sysTables[ID_TRIGGER_ROUTINE_USAGE];

            if (t == null)
            {
                t = createBlankTable(sysTableHsqlNames[ID_TRIGGER_ROUTINE_USAGE]);

                addColumn(t, "TRIGGER_CATALOG", SQL_IDENTIFIER);
                addColumn(t, "TRIGGER_SCHEMA", SQL_IDENTIFIER);
                addColumn(t, "TRIGGER_NAME", SQL_IDENTIFIER);     // not null
                addColumn(t, "SPECIFIC_CATALOG", SQL_IDENTIFIER);
                addColumn(t, "SPECIFIC_SCHEMA", SQL_IDENTIFIER);
                addColumn(t, "SPECIFIC_NAME", SQL_IDENTIFIER);    // not null

                QNameManager.QName name = QNameManager.newInfoSchemaObjectName(
                    sysTableHsqlNames[ID_TRIGGER_ROUTINE_USAGE].name, false,
                    SchemaObjectTypes.INDEX);

                t.createPrimaryKey(name, new int[] {
                0, 1, 2, 3, 4, 5
            }, false);

                return t;
            }

            PersistentStore store = database.persistentStoreCollection.getStore(t);

            // column number mappings
            int trigger_catalog = 0;
            int trigger_schema = 1;
            int trigger_name = 2;
            int specific_catalog = 3;
            int specific_schema = 4;
            int specific_name = 5;
            Iterator it;
            Object[] row;

            it = database.schemaManager.databaseObjectIterator(
                SchemaObjectTypes.TRIGGER);

            while (it.hasNext())
            {
                TriggerDef trigger = (TriggerDef)it.next();

                if (!session.getGrantee().isAccessible(trigger))
                {
                    continue;
                }

                OrderedHashSet set = trigger.getReferences();

                for (int i = 0; i < set.size(); i++)
                {
                    QNameManager.QName refName = (QNameManager.QName)set.get(i);

                    if (refName.type != SchemaObjectTypes.SPECIFIC_ROUTINE)
                    {
                        continue;
                    }

                    if (!session.getGrantee().isAccessible(refName))
                    {
                        continue;
                    }

                    row = t.getEmptyRowData();
                    row[trigger_catalog] = database.getCatalogName().originalName;
                    row[trigger_schema] = trigger.getSchemaName().originalName;
                    row[trigger_name] = trigger.getName().originalName;
                    row[specific_catalog] = database.getCatalogName().originalName;
                    row[specific_schema] = refName.schema.originalName;
                    row[specific_name] = refName.originalName;

                    try
                    {
                        t.insertSys(store, row);
                    }
                    catch (CoreException ) { }
                }
            }

            return t;
        }

        Table TRIGGER_SEQUENCE_USAGE()
        {

            Table t = sysTables[ID_TRIGGER_SEQUENCE_USAGE];

            if (t == null)
            {
                t = createBlankTable(sysTableHsqlNames[ID_TRIGGER_SEQUENCE_USAGE]);

                addColumn(t, "TRIGGER_CATALOG", SQL_IDENTIFIER);
                addColumn(t, "TRIGGER_SCHEMA", SQL_IDENTIFIER);
                addColumn(t, "TRIGGER_NAME", SQL_IDENTIFIER);     // not null
                addColumn(t, "SEQUENCE_CATALOG", SQL_IDENTIFIER);
                addColumn(t, "SEQUENCE_SCHEMA", SQL_IDENTIFIER);
                addColumn(t, "SEQUENCE_NAME", SQL_IDENTIFIER);    // not null

                QNameManager.QName name = QNameManager.newInfoSchemaObjectName(
                    sysTableHsqlNames[ID_TRIGGER_SEQUENCE_USAGE].name, false,
                    SchemaObjectTypes.INDEX);

                t.createPrimaryKey(name, new int[] {
                0, 1, 2, 3, 4, 5
            }, false);

                return t;
            }

            PersistentStore store = database.persistentStoreCollection.getStore(t);

            // column number mappings
            int trigger_catalog = 0;
            int trigger_schema = 1;
            int trigger_name = 2;
            int sequence_catalog = 3;
            int sequence_schema = 4;
            int sequence_name = 5;
            Iterator it;
            Object[] row;

            it = database.schemaManager.databaseObjectIterator(
                SchemaObjectTypes.TRIGGER);

            while (it.hasNext())
            {
                TriggerDef trigger = (TriggerDef)it.next();

                if (!session.getGrantee().isAccessible(trigger))
                {
                    continue;
                }

                OrderedHashSet set = trigger.getReferences();

                for (int i = 0; i < set.size(); i++)
                {
                    QNameManager.QName refName = (QNameManager.QName)set.get(i);

                    if (refName.type != SchemaObjectTypes.SEQUENCE)
                    {
                        continue;
                    }

                    if (!session.getGrantee().isAccessible(refName))
                    {
                        continue;
                    }

                    row = t.getEmptyRowData();
                    row[trigger_catalog] = database.getCatalogName().originalName;
                    row[trigger_schema] = trigger.getSchemaName().originalName;
                    row[trigger_name] = trigger.getName().originalName;
                    row[sequence_catalog] = database.getCatalogName().originalName;
                    row[sequence_schema] = refName.schema.originalName;
                    row[sequence_name] = refName.originalName;

                    try
                    {
                        t.insertSys(store, row);
                    }
                    catch (CoreException ) { }
                }
            }

            // Initialization
            return t;
        }

        Table TRIGGER_TABLE_USAGE()
        {

            Table t = sysTables[ID_TRIGGER_TABLE_USAGE];

            if (t == null)
            {
                t = createBlankTable(sysTableHsqlNames[ID_TRIGGER_TABLE_USAGE]);

                addColumn(t, "TRIGGER_CATALOG", SQL_IDENTIFIER);
                addColumn(t, "TRIGGER_SCHEMA", SQL_IDENTIFIER);
                addColumn(t, "TRIGGER_NAME", SQL_IDENTIFIER);    // not null
                addColumn(t, "TABLE_CATALOG", SQL_IDENTIFIER);
                addColumn(t, "TABLE_SCHEMA", SQL_IDENTIFIER);
                addColumn(t, "TABLE_NAME", SQL_IDENTIFIER);      // not null

                QNameManager.QName name = QNameManager.newInfoSchemaObjectName(
                    sysTableHsqlNames[ID_TRIGGER_TABLE_USAGE].name, false,
                    SchemaObjectTypes.INDEX);

                t.createPrimaryKey(name, new int[] {
                0, 1, 2, 3, 4, 5
            }, false);

                return t;
            }

            PersistentStore store = database.persistentStoreCollection.getStore(t);

            // column number mappings
            int trigger_catalog = 0;
            int trigger_schema = 1;
            int trigger_name = 2;
            int table_catalog = 3;
            int table_schema = 4;
            int table_name = 5;
            Iterator it;
            Object[] row;

            it = database.schemaManager.databaseObjectIterator(
                SchemaObjectTypes.TRIGGER);

            while (it.hasNext())
            {
                TriggerDef trigger = (TriggerDef)it.next();

                if (!session.getGrantee().isAccessible(trigger))
                {
                    continue;
                }

                OrderedHashSet set = trigger.getReferences();

                for (int i = 0; i < set.size(); i++)
                {
                    QNameManager.QName refName = (QNameManager.QName)set.get(i);

                    if (refName.type != SchemaObjectTypes.TABLE
                            && refName.type != SchemaObjectTypes.VIEW)
                    {
                        continue;
                    }

                    if (!session.getGrantee().isAccessible(refName))
                    {
                        continue;
                    }

                    row = t.getEmptyRowData();
                    row[trigger_catalog] = database.getCatalogName().originalName;
                    row[trigger_schema] = trigger.getSchemaName().originalName;
                    row[trigger_name] = trigger.getName().originalName;
                    row[table_catalog] = database.getCatalogName().originalName;
                    row[table_schema] = refName.schema.originalName;
                    row[table_name] = refName.originalName;

                    try
                    {
                        t.insertSys(store, row);
                    }
                    catch (CoreException ) { }
                }
            }

            // Initialization
            return t;
        }

        Table TRIGGERS()
        {

            Table t = sysTables[ID_TRIGGERS];

            if (t == null)
            {
                t = createBlankTable(sysTableHsqlNames[ID_TRIGGERS]);

                addColumn(t, "TRIGGER_CATALOG", SQL_IDENTIFIER);
                addColumn(t, "TRIGGER_SCHEMA", SQL_IDENTIFIER);
                addColumn(t, "TRIGGER_NAME", SQL_IDENTIFIER);
                addColumn(t, "EVENT_MANIPULATION", SQL_IDENTIFIER);
                addColumn(t, "EVENT_OBJECT_CATALOG", SQL_IDENTIFIER);
                addColumn(t, "EVENT_OBJECT_SCHEMA", SQL_IDENTIFIER);
                addColumn(t, "EVENT_OBJECT_TABLE", SQL_IDENTIFIER);
                addColumn(t, "ACTION_ORDER", CHARACTER_DATA);
                addColumn(t, "ACTION_CONDITION", CHARACTER_DATA);
                addColumn(t, "ACTION_STATEMENT", CHARACTER_DATA);
                addColumn(t, "ACTION_ORIENTATION", CHARACTER_DATA);
                addColumn(t, "ACTION_TIMING", CHARACTER_DATA);
                addColumn(t, "ACTION_REFERENCE_OLD_TABLE", SQL_IDENTIFIER);
                addColumn(t, "ACTION_REFERENCE_NEW_TABLE", SQL_IDENTIFIER);
                addColumn(t, "ACTION_REFERENCE_OLD_ROW", SQL_IDENTIFIER);
                addColumn(t, "ACTION_REFERENCE_NEW_ROW", SQL_IDENTIFIER);
                addColumn(t, "CREATED", TIME_STAMP);

                QNameManager.QName name = QNameManager.newInfoSchemaObjectName(
                    sysTableHsqlNames[ID_TRIGGERS].name, false, SchemaObjectTypes.INDEX);

                t.createPrimaryKey(name, new int[] {
                0, 1, 2
            }, false);

                return t;
            }

            PersistentStore store = database.persistentStoreCollection.getStore(t);

            // column number mappings
            int trigger_catalog = 0;
            int trigger_schema = 1;
            int trigger_name = 2;
            int event_manipulation = 3;
            int event_object_catalog = 4;
            int event_object_schema = 5;
            int event_object_table = 6;
            int action_order = 7;
            int action_condition = 8;
            int action_statement = 9;
            int action_orientation = 10;
            int action_timing = 11;
            int action_reference_old_table = 12;
            int action_reference_new_table = 13;
            int action_reference_old_row = 14;
            int action_reference_new_row = 15;
            int created = 16;
            Iterator it;
            Object[] row;

            it = database.schemaManager.databaseObjectIterator(
                SchemaObjectTypes.TRIGGER);

            while (it.hasNext())
            {
                TriggerDef trigger = (TriggerDef)it.next();

                if (!session.getGrantee().isAccessible(trigger))
                {
                    continue;
                }

                row = t.getEmptyRowData();
                row[trigger_catalog] = database.getCatalogName().originalName;
                row[trigger_schema] = trigger.getSchemaName().originalName;
                row[trigger_name] = trigger.getName().originalName;
                row[event_manipulation] = trigger.getEventTypeString();
                row[event_object_catalog] = database.getCatalogName().originalName;
                row[event_object_schema] = trigger.getTable().getSchemaName().originalName;
                row[event_object_table] = trigger.getTable().getName().originalName;

                int order =
                    trigger.getTable().getTriggerIndex(trigger.getName().originalName);

                row[action_order] = (order);
                row[action_condition] = trigger.getConditionSQL();
                row[action_statement] = trigger.getProcedureSQL();
                row[action_orientation] = trigger.getActionOrientationString();
                row[action_timing] = trigger.getActionTimingString();
                row[action_reference_old_table] =
                    trigger.getOldTransitionTableName();
                row[action_reference_new_table] =
                    trigger.getNewTransitionTableName();
                row[action_reference_old_row] = trigger.getOldTransitionRowName();
                row[action_reference_new_row] = trigger.getNewTransitionRowName();
                row[created] = null;

                t.insertSys(store, row);
            }

            // Initialization
            return t;
        }

        Table TRIGGERED_UPDATE_COLUMNS()
        {

            Table t = sysTables[ID_TRIGGERED_UPDATE_COLUMNS];

            if (t == null)
            {
                t = createBlankTable(sysTableHsqlNames[ID_TRIGGERED_UPDATE_COLUMNS]);

                addColumn(t, "TRIGGER_CATALOG", SQL_IDENTIFIER);
                addColumn(t, "TRIGGER_SCHEMA", SQL_IDENTIFIER);
                addColumn(t, "TRIGGER_NAME", SQL_IDENTIFIER);            // not null
                addColumn(t, "EVENT_OBJECT_CATALOG", SQL_IDENTIFIER);    // not null
                addColumn(t, "EVENT_OBJECT_SCHEMA", SQL_IDENTIFIER);
                addColumn(t, "EVENT_OBJECT_TABLE", SQL_IDENTIFIER);
                addColumn(t, "EVENT_OBJECT_COLUMN", SQL_IDENTIFIER);     // not null

                QNameManager.QName name = QNameManager.newInfoSchemaObjectName(
                    sysTableHsqlNames[ID_TRIGGERED_UPDATE_COLUMNS].name, false,
                    SchemaObjectTypes.INDEX);

                t.createPrimaryKey(name, new int[] {
                0, 1, 2, 3, 4, 5, 6
            }, false);

                return t;
            }

            PersistentStore store = database.persistentStoreCollection.getStore(t);

            // column number mappings
            int trigger_catalog = 0;
            int trigger_schema = 1;
            int trigger_name = 2;
            int event_object_catalog = 3;
            int event_object_schema = 4;
            int event_object_table = 5;
            int event_object_column = 6;
            Iterator it;
            Object[] row;

            it = database.schemaManager.databaseObjectIterator(
                SchemaObjectTypes.TRIGGER);

            while (it.hasNext())
            {
                TriggerDef trigger = (TriggerDef)it.next();

                if (!session.getGrantee().isAccessible(trigger))
                {
                    continue;
                }

                int[] colIndexes = trigger.getUpdateColumnIndexes();

                if (colIndexes == null)
                {
                    continue;
                }

                for (int i = 0; i < colIndexes.Length; i++)
                {
                    ColumnSchema column =
                        trigger.getTable().getColumn(colIndexes[i]);

                    row = t.getEmptyRowData();
                    row[trigger_catalog] = database.getCatalogName().originalName;
                    row[trigger_schema] = trigger.getSchemaName().originalName;
                    row[trigger_name] = trigger.getName().originalName;
                    row[event_object_catalog] = database.getCatalogName().originalName;
                    row[event_object_schema] =
                        trigger.getTable().getSchemaName().originalName;
                    row[event_object_table] = trigger.getTable().getName().originalName;
                    row[event_object_column] = column.getNameString();

                    t.insertSys(store, row);
                }
            }

            // Initialization
            return t;
        }

        Table UDT_PRIVILEGES()
        {

            Table t = sysTables[ID_UDT_PRIVILEGES];

            if (t == null)
            {
                t = createBlankTable(sysTableHsqlNames[ID_UDT_PRIVILEGES]);

                addColumn(t, "GRANTOR", SQL_IDENTIFIER);
                addColumn(t, "GRANTEE", SQL_IDENTIFIER);
                addColumn(t, "UDT_CATALOG", SQL_IDENTIFIER);
                addColumn(t, "UDT_SCHEMA", SQL_IDENTIFIER);
                addColumn(t, "UDT_NAME", SQL_IDENTIFIER);
                addColumn(t, "PRIVILEGE_TYPE", CHARACTER_DATA);
                addColumn(t, "IS_GRANTABLE", YES_OR_NO);

                QNameManager.QName name = QNameManager.newInfoSchemaObjectName(
                    sysTableHsqlNames[ID_UDT_PRIVILEGES].name, false,
                    SchemaObjectTypes.INDEX);

                t.createPrimaryKey(name, new int[] {
                0, 1, 2, 3, 4
            }, false);

                return t;
            }

            int grantor = 0;
            int grantee = 1;
            int udt_catalog = 2;
            int udt_schema = 3;
            int udt_name = 4;
            int privilege_type = 5;
            int is_grantable = 6;
            PersistentStore store = database.persistentStoreCollection.getStore(t);
            Iterator objects =
                database.schemaManager.databaseObjectIterator(SchemaObjectTypes.TYPE);
            OrderedHashSet grantees =
                session.getGrantee().getGranteeAndAllRolesWithPublic();

            while (objects.hasNext())
            {
                SchemaObject obj = (SchemaObject)objects.next();

                if (obj.getType() != SchemaObjectTypes.TYPE)
                {
                    continue;
                }

                for (int i = 0; i < grantees.size(); i++)
                {
                    Grantee granteeObject = (Grantee)grantees.get(i);
                    OrderedHashSet rights =
                        granteeObject.getAllDirectPrivileges(obj);
                    OrderedHashSet grants =
                        granteeObject.getAllGrantedPrivileges(obj);

                    if (!grants.isEmpty())
                    {
                        grants.addAll(rights);

                        rights = grants;
                    }

                    for (int j = 0; j < rights.size(); j++)
                    {
                        Right right = (Right)rights.get(j);
                        Right grantableRight = right.getGrantableRights();
                        Object[] row;

                        row = t.getEmptyRowData();
                        row[grantor] = right.getGrantor().getName().originalName;
                        row[grantee] = right.getGrantee().getName().originalName;
                        row[udt_catalog] = database.getCatalogName().originalName;
                        row[udt_schema] = obj.getSchemaName().originalName;
                        row[udt_name] = obj.getName().originalName;
                        row[privilege_type] = Tokens.T_USAGE;
                        row[is_grantable] =
                            right.getGrantee() == obj.getOwner()
                            || grantableRight.isFull() ? Tokens.T_YES
                                                       : Tokens.T_NO; ;

                        try
                        {
                            t.insertSys(store, row);
                        }
                        catch (CoreException ) { }
                    }
                }
            }

            return t;
        }

        /**
         * The USAGE_PRIVILEGES view has one row for each usage privilege
         * descriptor. <p>
         *
         * It effectively contains a representation of the usage privilege
         * descriptors. <p>
         *
         * <b>Definition:</b> <p>
         *
         * <pre class="SqlCodeExample">
         * CREATE TABLE SYSTEM_USAGE_PRIVILEGES (
         *      GRANTOR         VARCHAR NOT NULL,
         *      GRANTEE         VARCHAR NOT NULL,
         *      OBJECT_CATALOG  VARCHAR NULL,
         *      OBJECT_SCHEMA   VARCHAR NULL,
         *      OBJECT_NAME     VARCHAR NOT NULL,
         *      OBJECT_TYPE     VARCHAR NOT NULL
         *
         *          CHECK ( OBJECT_TYPE IN (
         *                      'DOMAIN',
         *                      'CHARACTER SET',
         *                      'COLLATION',
         *                      'TRANSLATION',
         *                      'SEQUENCE' ) ),
         *
         *      IS_GRANTABLE    VARCHAR NOT NULL
         *
         *          CHECK ( IS_GRANTABLE IN ( 'YES', 'NO' ) ),
         *
         *      UNIQUE( GRANTOR, GRANTEE, OBJECT_CATALOG,
         *              OBJECT_SCHEMA, OBJECT_NAME, OBJECT_TYPE )
         * )
         * </pre>
         *
         * <b>Description:</b><p>
         *
         * <ol>
         * <li> The value of GRANTOR is the &lt;authorization identifier&gt; of the
         *      user or role who granted usage privileges on the object of the type
         *      identified by OBJECT_TYPE that is identified by OBJECT_CATALOG,
         *      OBJECT_SCHEMA, and OBJECT_NAME, to the user or role identified by the
         *      value of GRANTEE forthe usage privilege being described. <p>
         *
         * <li> The value of GRANTEE is the &lt;authorization identifier&gt; of some
         *      user or role, or PUBLIC to indicate all users, to whom the usage
         *      privilege being described is granted. <p>
         *
         * <li> The values of OBJECT_CATALOG, OBJECT_SCHEMA, and OBJECT_NAME are the
         *      catalog name, unqualified schema name, and qualified identifier,
         *      respectively, of the object to which the privilege applies. <p>
         *
         * <li> The values of OBJECT_TYPE have the following meanings: <p>
         *
         *      <table border cellpadding="3">
         *          <tr>
         *              <td nowrap>DOMAIN</td>
         *              <td nowrap>The object to which the privilege applies is
         *                         a domain.</td>
         *          <tr>
         *          <tr>
         *              <td nowrap>CHARACTER SET</td>
         *              <td nowrap>The object to which the privilege applies is a
         *                         character set.</td>
         *          <tr>
         *          <tr>
         *              <td nowrap>COLLATION</td>
         *              <td nowrap>The object to which the privilege applies is a
         *                         collation.</td>
         *          <tr>
         *          <tr>
         *              <td nowrap>TRANSLATION</td>
         *              <td nowrap>The object to which the privilege applies is a
         *                         transliteration.</td>
         *          <tr>
         *          <tr>
         *              <td nowrap>SEQUENCE</td>
         *              <td nowrap>The object to which the privilege applies is a
         *                         sequence generator.</td>
         *          <tr>
         *      </table> <p>
         *
         * <li> The values of IS_GRANTABLE have the following meanings: <p>
         *
         *      <table border cellpadding="3">
         *          <tr>
         *              <td nowrap>YES</td>
         *              <td nowrap>The privilege being described was granted
         *                         WITH GRANT OPTION and is thus grantable.</td>
         *          <tr>
         *          <tr>
         *              <td nowrap>NO</td>
         *              <td nowrap>The privilege being described was not granted
         *                  WITH GRANT OPTION and is thus not grantable.</td>
         *          <tr>
         *      </table> <p>
         * <ol>
         *
         * @return Table
         */
        Table USAGE_PRIVILEGES()
        {

            Table t = sysTables[ID_USAGE_PRIVILEGES];

            if (t == null)
            {
                t = createBlankTable(sysTableHsqlNames[ID_USAGE_PRIVILEGES]);

                addColumn(t, "GRANTOR", SQL_IDENTIFIER);        // not null
                addColumn(t, "GRANTEE", SQL_IDENTIFIER);        // not null
                addColumn(t, "OBJECT_CATALOG", SQL_IDENTIFIER);
                addColumn(t, "OBJECT_SCHEMA", SQL_IDENTIFIER);
                addColumn(t, "OBJECT_NAME", SQL_IDENTIFIER);    // not null
                addColumn(t, "OBJECT_TYPE", CHARACTER_DATA);    // not null
                addColumn(t, "PRIVILEGE_TYPE", CHARACTER_DATA);
                addColumn(t, "IS_GRANTABLE", YES_OR_NO);        // not null

                // order: COLUMN_NAME, PRIVILEGE
                // for unique: GRANTEE, GRANTOR, TABLE_NAME, TABLE_SCHEM, TABLE_CAT
                // false PK, as TABLE_SCHEM and/or TABLE_CAT may be null
                QNameManager.QName name = QNameManager.newInfoSchemaObjectName(
                    sysTableHsqlNames[ID_USAGE_PRIVILEGES].name, false,
                    SchemaObjectTypes.INDEX);

                t.createPrimaryKey(name, new int[] {
                0, 1, 2, 3, 4, 5, 6, 7
            }, false);

                return t;
            }

            //
            Object[] row;

            //
            int grantor = 0;
            int grantee = 1;
            int object_catalog = 2;
            int object_schema = 3;
            int object_name = 4;
            int object_type = 5;
            int privilege_type = 6;
            int is_grantable = 7;
            PersistentStore store = database.persistentStoreCollection.getStore(t);
            Iterator objects =
                new WrapperIterator(database.schemaManager
                    .databaseObjectIterator(SchemaObjectTypes.SEQUENCE), database
                    .schemaManager.databaseObjectIterator(SchemaObjectTypes.COLLATION));

            objects = new WrapperIterator(
                objects,
                database.schemaManager.databaseObjectIterator(
                    SchemaObjectTypes.CHARSET));
            objects = new WrapperIterator(
                objects,
                database.schemaManager.databaseObjectIterator(
                    SchemaObjectTypes.DOMAIN));

            /*
                    objects = new WrapperIterator(
                        objects,
                        database.schemaManager.databaseObjectIterator(SchemaObjectTypes.TYPE));
            */
            OrderedHashSet grantees =
                session.getGrantee().getGranteeAndAllRolesWithPublic();

            while (objects.hasNext())
            {
                SchemaObject obj = (SchemaObject)objects.next();

                for (int i = 0; i < grantees.size(); i++)
                {
                    Grantee granteeObject = (Grantee)grantees.get(i);
                    OrderedHashSet rights =
                        granteeObject.getAllDirectPrivileges(obj);
                    OrderedHashSet grants =
                        granteeObject.getAllGrantedPrivileges(obj);

                    if (!grants.isEmpty())
                    {
                        grants.addAll(rights);

                        rights = grants;
                    }

                    for (int j = 0; j < rights.size(); j++)
                    {
                        Right right = (Right)rights.get(j);
                        Right grantableRight = right.getGrantableRights();

                        row = t.getEmptyRowData();
                        row[grantor] = right.getGrantor().getName().originalName;
                        row[grantee] = right.getGrantee().getName().originalName;
                        row[object_catalog] = database.getCatalogName().originalName;
                        row[object_schema] = obj.getSchemaName().originalName;
                        row[object_name] = obj.getName().originalName;
                        row[object_type] =
                            SchemaObjectSet.getName(obj.getName().type);
                        row[privilege_type] = Tokens.T_USAGE;
                        row[is_grantable] =
                            right.getGrantee() == obj.getOwner()
                            || grantableRight.isFull() ? Tokens.T_YES
                                                       : Tokens.T_NO; ;

                        try
                        {
                            t.insertSys(store, row);
                        }
                        catch (CoreException ) { }
                    }
                }
            }

            return t;
        }

        Table USER_DEFINED_TYPES()
        {

            Table t = sysTables[ID_USER_DEFINED_TYPES];

            if (t == null)
            {
                t = createBlankTable(sysTableHsqlNames[ID_USER_DEFINED_TYPES]);

                addColumn(t, "USER_DEFINED_TYPE_CATALOG", SQL_IDENTIFIER);
                addColumn(t, "USER_DEFINED_TYPE_SCHEMA", SQL_IDENTIFIER);
                addColumn(t, "USER_DEFINED_TYPE_NAME", SQL_IDENTIFIER);
                addColumn(t, "USER_DEFINED_TYPE_CATEGORY", SQL_IDENTIFIER);
                addColumn(t, "IS_INSTANTIABLE", YES_OR_NO);
                addColumn(t, "IS_FINAL", YES_OR_NO);
                addColumn(t, "ORDERING_FORM", SQL_IDENTIFIER);
                addColumn(t, "ORDERING_CATEGORY", SQL_IDENTIFIER);
                addColumn(t, "ORDERING_ROUTINE_CATALOG", SQL_IDENTIFIER);
                addColumn(t, "ORDERING_ROUTINE_SCHEMA", SQL_IDENTIFIER);
                addColumn(t, "ORDERING_ROUTINE_NAME", SQL_IDENTIFIER);
                addColumn(t, "REFERENCE_TYPE", SQL_IDENTIFIER);
                addColumn(t, "DATA_TYPE", CHARACTER_DATA);
                addColumn(t, "CHARACTER_MAXIMUM_LENGTH", CARDINAL_NUMBER);
                addColumn(t, "CHARACTER_OCTET_LENGTH", CARDINAL_NUMBER);
                addColumn(t, "CHARACTER_SET_CATALOG", SQL_IDENTIFIER);
                addColumn(t, "CHARACTER_SET_SCHEMA", SQL_IDENTIFIER);
                addColumn(t, "CHARACTER_SET_NAME", SQL_IDENTIFIER);
                addColumn(t, "COLLATION_CATALOG", SQL_IDENTIFIER);
                addColumn(t, "COLLATION_SCHEMA", SQL_IDENTIFIER);
                addColumn(t, "COLLATION_NAME", SQL_IDENTIFIER);
                addColumn(t, "NUMERIC_PRECISION", CARDINAL_NUMBER);
                addColumn(t, "NUMERIC_PRECISION_RADIX", CARDINAL_NUMBER);
                addColumn(t, "NUMERIC_SCALE", CARDINAL_NUMBER);
                addColumn(t, "DATETIME_PRECISION", CARDINAL_NUMBER);
                addColumn(t, "INTERVAL_TYPE", CHARACTER_DATA);
                addColumn(t, "INTERVAL_PRECISION", CARDINAL_NUMBER);
                addColumn(t, "SOURCE_DTD_IDENTIFIER", CHARACTER_DATA);
                addColumn(t, "REF_DTD_IDENTIFIER", CHARACTER_DATA);
                addColumn(t, "DECLARED_DATA_TYPE", CHARACTER_DATA);
                addColumn(t, "DECLARED_NUMERIC_PRECISION", CARDINAL_NUMBER);
                addColumn(t, "DECLARED_NUMERIC_SCALE", CARDINAL_NUMBER);
                addColumn(t, "EXTERNAL_NAME", CHARACTER_DATA);
                addColumn(t, "EXTERNAL_LANGUAGE", CHARACTER_DATA);
                addColumn(t, "JAVA_INTERFACE", CHARACTER_DATA);

                QNameManager.QName name = QNameManager.newInfoSchemaObjectName(
                    sysTableHsqlNames[ID_USER_DEFINED_TYPES].name, false,
                    SchemaObjectTypes.INDEX);

                t.createPrimaryKey(name, new int[] {
                0, 1, 2, 4, 5, 6
            }, false);

                return t;
            }

            PersistentStore store = database.persistentStoreCollection.getStore(t);
            int user_defined_type_catalog = 0;
            int user_defined_type_schema = 1;
            int user_defined_type_name = 2;
            int user_defined_type_category = 3;
            int is_instantiable = 4;
            int is_final = 5;
            int ordering_form = 6;
            //int ordering_category = 7;
            //int ordering_routine_catalog = 8;
            //int ordering_routine_schema = 9;
            //int ordering_routine_name = 10;
            //int reference_type = 11;
            int data_type = 12;
            int character_maximum_length = 13;
            int character_octet_length = 14;
            int character_set_catalog = 15;
            int character_set_schema = 16;
            int character_set_name = 17;
            int collation_catalog = 18;
            int collation_schema = 19;
            int collation_name = 20;
            int numeric_precision = 21;
            int numeric_precision_radix = 22;
            int numeric_scale = 23;
            int datetime_precision = 24;
            int interval_type = 25;
            int interval_precision = 26;
            int source_dtd_identifier = 27;
            //int ref_dtd_identifier = 28;
            int declared_data_type = 29;
            int declared_numeric_precision = 30;
            int declared_numeric_scale = 31;
            Iterator it =
                database.schemaManager.databaseObjectIterator(SchemaObjectTypes.TYPE);

            while (it.hasNext())
            {
                SqlType type = (SqlType)it.next();

                if (!type.isDistinctType())
                {
                    continue;
                }

                Object[] row = t.getEmptyRowData();

                row[user_defined_type_catalog] = database.getCatalogName().originalName;
                row[user_defined_type_schema] = type.getSchemaName().originalName;
                row[user_defined_type_name] = type.getName().originalName;
                row[data_type] = type.getFullNameString();
                row[declared_data_type] = type.getFullNameString();
                row[user_defined_type_category] = "DISTINCT";
                row[is_instantiable] = "YES";
                row[is_final] = "YES";
                row[ordering_form] = "FULL";

                // common type block
                if (type.isCharacterType())
                {
                    row[character_maximum_length] =
                        (long)(type.precision);
                    row[character_octet_length] = (long)(type.precision
                            * 2);
                    row[character_set_catalog] = database.getCatalogName().originalName;
                    row[character_set_schema] =
                        ((CharacterType)type).getCharacterSet().getSchemaName()
                            .originalName;
                    row[character_set_name] =
                        ((CharacterType)type).getCharacterSet().getName().originalName;
                    row[collation_catalog] = database.getCatalogName().originalName;
                    row[collation_schema] =
                        ((CharacterType)type).getCollation().getSchemaName().originalName;
                    row[collation_name] =
                        ((CharacterType)type).getCollation().getName().originalName;
                }
                else if (type.isNumberType())
                {
                    row[numeric_precision] = (long)(
                        ((NumberType)type).getNumericPrecisionInRadix());
                    row[declared_numeric_precision] = (long)(
                        ((NumberType)type).getNumericPrecisionInRadix());

                    if (type.isExactNumberType())
                    {
                        row[numeric_scale] = row[declared_numeric_scale] =
                            (long)(type.scale);
                    }

                    row[numeric_precision_radix] =
                        (long)(type.getPrecisionRadix());
                }
                else if (type.isBooleanType()) { }
                else if (type.isDateTimeType())
                {
                    row[datetime_precision] = (long)(type.scale);
                }
                else if (type.isIntervalType())
                {
                    row[data_type] = "INTERVAL";
                    row[interval_type] =
                        IntervalType.getQualifier(type.typeCode);
                    row[interval_precision] = (long)(type.precision);
                    row[datetime_precision] = (long)(type.scale);
                }
                else if (type.isBinaryType())
                {
                    row[character_maximum_length] =
                        (long)(type.precision);
                    row[character_octet_length] =
                        (long)(type.precision);
                }
                else if (type.isBitType())
                {
                    row[character_maximum_length] =
                        (long)(type.precision);
                    row[character_octet_length] =
                        (long)(type.precision);
                }

                // end common block
                row[source_dtd_identifier] = row[user_defined_type_name];

                t.insertSys(store, row);
            }

            return t;
        }

        /**
         * The VIEW_COLUMN_USAGE table has one row for each column of a
         * table that is explicitly or implicitly referenced in the
         * &lt;query expression&gt; of the view being described. <p>
         *
         * <b>Definition:</b> <p>
         *
         * <pre class="SqlCodeExample">
         * CREATE TABLE SYSTEM_VIEW_COLUMN_USAGE (
         *      VIEW_CATALOG    VARCHAR NULL,
         *      VIEW_SCHEMA     VARCHAR NULL,
         *      VIEW_NAME       VARCHAR NOT NULL,
         *      TABLE_CATALOG   VARCHAR NULL,
         *      TABLE_SCHEMA    VARCHAR NULL,
         *      TABLE_NAME      VARCHAR NOT NULL,
         *      COLUMN_NAME     VARCHAR NOT NULL,
         *      UNIQUE ( VIEW_CATALOG, VIEW_SCHEMA, VIEW_NAME,
         *               TABLE_CATALOG, TABLE_SCHEMA, TABLE_NAME,
         *               COLUMN_NAME )
         * )
         * </pre>
         *
         * <b>Description:</b> <p>
         *
         * <ol>
         * <li> The values of VIEW_CATALOG, VIEW_SCHEMA, and VIEW_NAME are the
         *      catalog name, unqualified schema name, and qualified identifier,
         *      respectively, of the view being described. <p>
         *
         * <li> The values of TABLE_CATALOG, TABLE_SCHEMA, TABLE_NAME, and
         *      COLUMN_NAME are the catalog name, unqualified schema name,
         *      qualified identifier, and column name, respectively, of a column
         *      of a table that is explicitly or implicitly referenced in the
         *      &lt;query expression&gt; of the view being described.
         * </ol>
         *
         * @return Table
         */
        Table VIEW_COLUMN_USAGE()
        {

            Table t = sysTables[ID_VIEW_COLUMN_USAGE];

            if (t == null)
            {
                t = createBlankTable(sysTableHsqlNames[ID_VIEW_COLUMN_USAGE]);

                addColumn(t, "VIEW_CATALOG", SQL_IDENTIFIER);
                addColumn(t, "VIEW_SCHEMA", SQL_IDENTIFIER);
                addColumn(t, "VIEW_NAME", SQL_IDENTIFIER);
                addColumn(t, "TABLE_CATALOG", SQL_IDENTIFIER);
                addColumn(t, "TABLE_SCHEMA", SQL_IDENTIFIER);
                addColumn(t, "TABLE_NAME", SQL_IDENTIFIER);
                addColumn(t, "COLUMN_NAME", SQL_IDENTIFIER);

                QNameManager.QName name = QNameManager.newInfoSchemaObjectName(
                    sysTableHsqlNames[ID_VIEW_COLUMN_USAGE].name, false,
                    SchemaObjectTypes.INDEX);

                t.createPrimaryKey(name, new int[] {
                0, 1, 2, 3, 4, 5, 6
            }, false);

                return t;
            }

            PersistentStore store = database.persistentStoreCollection.getStore(t);

            // Calculated column values
            String viewCatalog;
            String viewSchema;
            String viewName;

            // Intermediate holders
            Iterator tables;
            View view;
            Table table;
            Object[] row;
            Iterator iterator;

            // Column number mappings
            int view_catalog = 0;
            int view_schema = 1;
            int view_name = 2;
            int table_catalog = 3;
            int table_schema = 4;
            int table_name = 5;
            int column_name = 6;

            // Initialization
            tables =
                database.schemaManager.databaseObjectIterator(SchemaObjectTypes.TABLE);

            // Do it.
            while (tables.hasNext())
            {
                table = (Table)tables.next();

                if (table.isView()
                        && session.getGrantee().isFullyAccessibleByRole(
                            table.getName()))
                {

                    // fall through
                }
                else
                {
                    continue;
                }

                viewCatalog = database.getCatalogName().originalName;
                viewSchema = table.getSchemaName().originalName;
                viewName = table.getName().originalName;
                view = (View)table;

                OrderedHashSet references = view.getReferences();

                iterator = references.iterator();

                while (iterator.hasNext())
                {
                    QNameManager.QName refName = (QNameManager.QName)iterator.next();

                    if (refName.type != SchemaObjectTypes.COLUMN)
                    {
                        continue;
                    }

                    row = t.getEmptyRowData();
                    row[view_catalog] = viewCatalog;
                    row[view_schema] = viewSchema;
                    row[view_name] = viewName;
                    row[table_catalog] = viewCatalog;
                    row[table_schema] = refName.parent.schema.originalName;
                    row[table_name] = refName.parent.originalName;
                    row[column_name] = refName.originalName;

                    try
                    {
                        t.insertSys(store, row);
                    }
                    catch (CoreException ) { }
                }
            }

            return t;
        }

        /**
         * The VIEW_ROUTINE_USAGE table has one row for each SQL-invoked
         * routine identified as the subject routine of either a &lt;routine
         * invocation&gt;, a &lt;method reference&gt;, a &lt;method invocation&gt;,
         * or a &lt;static method invocation&gt; contained in a &lt;view
         * definition&gt;. <p>
         *
         * <b>Definition</b><p>
         *
         * <pre class="SqlCodeExample">
         * CREATE TABLE VIEW_ROUTINE_USAGE (
         *      TABLE_CATALOG       VARCHAR NULL,
         *      TABLE_SCHEMA        VARCHAR NULL,
         *      TABLE_NAME          VARCHAR NOT NULL,
         *      SPECIFIC_CATALOG    VARCHAR NULL,
         *      SPECIFIC_SCHEMA     VARCHAR NULL,
         *      SPECIFIC_NAME       VARCHAR NOT NULL,
         *      UNIQUE( TABLE_CATALOG, TABLE_SCHEMA, TABLE_NAME,
         *              SPECIFIC_CATALOG, SPECIFIC_SCHEMA,
         *              SPECIFIC_NAME )
         * )
         * </pre>
         *
         * <b>Description</b><p>
         *
         * <ol>
         * <li> The values of TABLE_CATALOG, TABLE_SCHEMA, and TABLE_NAME are the
         *      catalog name, unqualified schema name, and qualified identifier,
         *      respectively, of the viewed table being described. <p>
         *
         * <li> The values of SPECIFIC_CATALOG, SPECIFIC_SCHEMA, and SPECIFIC_NAME are
         *      the catalog name, unqualified schema name, and qualified identifier,
         *      respectively, of the specific name of R. <p>
         * </ol>
         *
         * @return Table
         */
        Table VIEW_ROUTINE_USAGE()
        {

            Table t = sysTables[ID_VIEW_ROUTINE_USAGE];

            if (t == null)
            {
                t = createBlankTable(sysTableHsqlNames[ID_VIEW_ROUTINE_USAGE]);

                addColumn(t, "VIEW_CATALOG", SQL_IDENTIFIER);
                addColumn(t, "VIEW_SCHEMA", SQL_IDENTIFIER);
                addColumn(t, "VIEW_NAME", SQL_IDENTIFIER);
                addColumn(t, "SPECIFIC_CATALOG", SQL_IDENTIFIER);
                addColumn(t, "SPECIFIC_SCHEMA", SQL_IDENTIFIER);
                addColumn(t, "SPECIFIC_NAME", SQL_IDENTIFIER);

                QNameManager.QName name = QNameManager.newInfoSchemaObjectName(
                    sysTableHsqlNames[ID_VIEW_ROUTINE_USAGE].name, false,
                    SchemaObjectTypes.INDEX);

                t.createPrimaryKey(name, new int[] {
                0, 1, 2, 3, 4, 5
            }, false);

                return t;
            }

            PersistentStore store = database.persistentStoreCollection.getStore(t);

            // Intermediate holders
            Iterator tables;
            Table table;
            Object[] row;

            // Column number mappings
            int view_catalog = 0;
            int view_schema = 1;
            int view_name = 2;
            int specific_catalog = 3;
            int specific_schema = 4;
            int specific_name = 5;

            // Initialization
            tables =
                database.schemaManager.databaseObjectIterator(SchemaObjectTypes.TABLE);

            // Do it.
            while (tables.hasNext())
            {
                table = (Table)tables.next();

                if (table.isView()
                        && session.getGrantee().isFullyAccessibleByRole(
                            table.getName()))
                {

                    // fall through
                }
                else
                {
                    continue;
                }

                OrderedHashSet set = table.getReferences();

                for (int i = 0; i < set.size(); i++)
                {
                    QNameManager.QName refName = (QNameManager.QName)set.get(i);

                    if (!session.getGrantee().isFullyAccessibleByRole(refName))
                    {
                        continue;
                    }

                    if (refName.type != SchemaObjectTypes.SPECIFIC_ROUTINE)
                    {
                        continue;
                    }

                    row = t.getEmptyRowData();
                    row[view_catalog] = database.getCatalogName().originalName;
                    row[view_schema] = table.getSchemaName().originalName;
                    row[view_name] = table.getName().originalName;
                    row[specific_catalog] = database.getCatalogName().originalName;
                    row[specific_schema] = refName.schema.originalName;
                    row[specific_name] = refName.originalName;

                    try
                    {
                        t.insertSys(store, row);
                    }
                    catch (CoreException ) { }
                }
            }

            return t;
        }

        /**
         * The VIEW_TABLE_USAGE table has one row for each table identified
         * by a &lt;table name&gt; simply contained in a &lt;table reference&gt;
         * that is contained in the &lt;query expression&gt; of a view. <p>
         *
         * <b>Definition</b><p>
         *
         * <pre class="SqlCodeExample">
         * CREATE TABLE SYSTEM_VIEW_TABLE_USAGE (
         *      VIEW_CATALOG    VARCHAR NULL,
         *      VIEW_SCHEMA     VARCHAR NULL,
         *      VIEW_NAME       VARCHAR NULL,
         *      TABLE_CATALOG   VARCHAR NULL,
         *      TABLE_SCHEMA    VARCHAR NULL,
         *      TABLE_NAME      VARCHAR NULL,
         *      UNIQUE( VIEW_CATALOG, VIEW_SCHEMA, VIEW_NAME,
         *              TABLE_CATALOG, TABLE_SCHEMA, TABLE_NAME )
         * )
         * </pre>
         *
         * <b>Description:</b><p>
         *
         * <ol>
         * <li> The values of VIEW_CATALOG, VIEW_SCHEMA, and VIEW_NAME are the
         *      catalog name, unqualified schema name, and qualified identifier,
         *      respectively, of the view being described. <p>
         *
         * <li> The values of TABLE_CATALOG, TABLE_SCHEMA, and TABLE_NAME are the
         *      catalog name, unqualified schema name, and qualified identifier,
         *      respectively, of a table identified by a &lt;table name&gt;
         *      simply contained in a &lt;table reference&gt; that is contained in
         *      the &lt;query expression&gt; of the view being described.
         * </ol>
         *
         * @return Table
         */
        Table VIEW_TABLE_USAGE()
        {

            Table t = sysTables[ID_VIEW_TABLE_USAGE];

            if (t == null)
            {
                t = createBlankTable(sysTableHsqlNames[ID_VIEW_TABLE_USAGE]);

                addColumn(t, "VIEW_CATALOG", SQL_IDENTIFIER);
                addColumn(t, "VIEW_SCHEMA", SQL_IDENTIFIER);
                addColumn(t, "VIEW_NAME", SQL_IDENTIFIER);     // not null
                addColumn(t, "TABLE_CATALOG", SQL_IDENTIFIER);
                addColumn(t, "TABLE_SCHEMA", SQL_IDENTIFIER);
                addColumn(t, "TABLE_NAME", SQL_IDENTIFIER);    // not null

                // false PK, as VIEW_CATALOG, VIEW_SCHEMA, TABLE_CATALOG, and/or
                // TABLE_SCHEMA may be NULL
                QNameManager.QName name = QNameManager.newInfoSchemaObjectName(
                    sysTableHsqlNames[ID_VIEW_TABLE_USAGE].name, false,
                    SchemaObjectTypes.INDEX);

                t.createPrimaryKey(name, new int[] {
                0, 1, 2, 3, 4, 5
            }, false);

                return t;
            }

            // Column number mappings
            int view_catalog = 0;
            int view_schema = 1;
            int view_name = 2;
            int table_catalog = 3;
            int table_schema = 4;
            int table_name = 5;

            //
            PersistentStore store = database.persistentStoreCollection.getStore(t);
            Iterator tables;
            Table table;
            Object[] row;

            // Initialization
            tables =
                database.schemaManager.databaseObjectIterator(SchemaObjectTypes.TABLE);

            // Do it.
            while (tables.hasNext())
            {
                table = (Table)tables.next();

                if (table.isView()
                        && session.getGrantee().isFullyAccessibleByRole(
                            table.getName()))
                {

                    // fall through
                }
                else
                {
                    continue;
                }

                OrderedHashSet references = table.getReferences();

                for (int i = 0; i < references.size(); i++)
                {
                    QNameManager.QName refName = (QNameManager.QName)references.get(i);

                    if (!session.getGrantee().isFullyAccessibleByRole(refName))
                    {
                        continue;
                    }

                    if (refName.type != SchemaObjectTypes.TABLE)
                    {
                        continue;
                    }

                    row = t.getEmptyRowData();
                    row[view_catalog] = database.getCatalogName().originalName;
                    row[view_schema] = table.getSchemaName().originalName;
                    row[view_name] = table.getName().originalName;
                    row[table_catalog] = database.getCatalogName().originalName;
                    row[table_schema] = refName.schema.originalName;
                    row[table_name] = refName.originalName;

                    try
                    {
                        t.insertSys(store, row);
                    }
                    catch (CoreException ) { }
                }
            }

            return t;
        }

        /**
         * The VIEWS view contains one row for each VIEW definition. <p>
         *
         * Each row is a description of the query expression that defines its view,
         * with the following columns:
         *
         * <pre class="SqlCodeExample">
         * TABLE_CATALOG    VARCHAR     name of view's defining catalog.
         * TABLE_SCHEMA     VARCHAR     name of view's defining schema.
         * TABLE_NAME       VARCHAR     the simple name of the view.
         * VIEW_DEFINITION  VARCHAR     the character representation of the
         *                              &lt;query expression&gt; contained in the
         *                              corresponding &lt;view descriptor&gt;.
         * CHECK_OPTION     VARCHAR     {"CASCADED" | "LOCAL" | "NONE"}
         * IS_UPDATABLE     VARCHAR     {"YES" | "NO"}
         * INSERTABLE_INTO VARCHAR      {"YES" | "NO"}
         * IS_TRIGGER_UPDATABLE        VARCHAR  {"YES" | "NO"}
         * IS_TRIGGER_DELETEABLE       VARCHAR  {"YES" | "NO"}
         * IS_TRIGGER_INSERTABLE_INTO  VARCHAR  {"YES" | "NO"}
         * </pre> <p>
         *
         * @return a tabular description of the text source of all
         *        <code>View</code> objects accessible to
         *        the user.
         */
        Table VIEWS()
        {

            Table t = sysTables[ID_VIEWS];

            if (t == null)
            {
                t = createBlankTable(sysTableHsqlNames[ID_VIEWS]);

                addColumn(t, "TABLE_CATALOG", SQL_IDENTIFIER);
                addColumn(t, "TABLE_SCHEMA", SQL_IDENTIFIER);
                addColumn(t, "TABLE_NAME", SQL_IDENTIFIER);               // not null
                addColumn(t, "VIEW_DEFINITION", CHARACTER_DATA);          // not null
                addColumn(t, "CHECK_OPTION", CHARACTER_DATA);             // not null
                addColumn(t, "IS_UPDATABLE", YES_OR_NO);                  // not null
                addColumn(t, "INSERTABLE_INTO", YES_OR_NO);               // not null
                addColumn(t, "IS_TRIGGER_UPDATABLE", YES_OR_NO);          // not null
                addColumn(t, "IS_TRIGGER_DELETABLE", YES_OR_NO);          // not null
                addColumn(t, "IS_TRIGGER_INSERTABLE_INTO", YES_OR_NO);    // not null

                // order TABLE_NAME
                // added for unique: TABLE_SCHEMA, TABLE_CATALOG
                // false PK, as TABLE_SCHEMA and/or TABLE_CATALOG may be null
                QNameManager.QName name = QNameManager.newInfoSchemaObjectName(
                    sysTableHsqlNames[ID_VIEWS].name, false, SchemaObjectTypes.INDEX);

                t.createPrimaryKey(name, new int[] {
                1, 2, 0
            }, false);

                return t;
            }

            PersistentStore store = database.persistentStoreCollection.getStore(t);
            Iterator tables;
            Table table;
            Object[] row;
            int table_catalog = 0;
            int table_schema = 1;
            int table_name = 2;
            int view_definition = 3;
            int check_option = 4;
            int is_updatable = 5;
            int insertable_into = 6;
            int is_trigger_updatable = 7;
            int is_trigger_deletable = 8;
            int is_trigger_insertable_into = 9;

            tables = allTables();

            while (tables.hasNext())
            {
                table = (Table)tables.next();

                if ((table.getSchemaName() != SqlInvariants
                        .INFORMATION_SCHEMA_QNAME && !table
                            .isView()) || !isAccessibleTable(table))
                {
                    continue;
                }

                row = t.getEmptyRowData();
                row[table_catalog] = database.getCatalogName().originalName;
                row[table_schema] = table.getSchemaName().originalName;
                row[table_name] = table.getName().originalName;

                String check = Tokens.T_NONE;

                if (table is View)
                {
                    if (session.getGrantee().isFullyAccessibleByRole(
                            table.getName()))
                    {
                        row[view_definition] = ((View)table).getStatement();
                    }

                    switch (((View)table).getCheckOption())
                    {

                        case SchemaObjectViewCheckModes.CHECK_NONE:
                            break;

                        case SchemaObjectViewCheckModes.CHECK_LOCAL:
                            check = Tokens.T_LOCAL;
                            break;

                        case SchemaObjectViewCheckModes.CHECK_CASCADE:
                            check = Tokens.T_CASCADED;
                            break;
                    }
                }

                row[check_option] = check;
                row[is_updatable] = table.isUpdatable() ? Tokens.T_YES
                                                                : Tokens.T_NO;
                row[insertable_into] = table.isInsertable() ? Tokens.T_YES
                                                                 : Tokens.T_NO;
                row[is_trigger_updatable] = null;    // only applies to INSTEAD OF triggers
                row[is_trigger_deletable] = null;
                row[is_trigger_insertable_into] = null;

                t.insertSys(store, row);
            }

            return t;
        }

        //------------------------------------------------------------------------------
        // SQL SCHEMATA BASE TABLES

        /**
         * ROLE_AUTHORIZATION_DESCRIPTORS<p>
         *
         * <b>Function</b><p>
         *
         * Contains a representation of the role authorization descriptors.<p>
         * <b>Definition</b>
         *
         * <pre class="SqlCodeExample">
         * CREATE TABLE ROLE_AUTHORIZATION_DESCRIPTORS (
         *      ROLE_NAME INFORMATION_SCHEMA.SQL_IDENTIFIER,
         *      GRANTEE INFORMATION_SCHEMA.SQL_IDENTIFIER,
         *      GRANTOR INFORMATION_SCHEMA.SQL_IDENTIFIER,
         *      IS_GRANTABLE INFORMATION_SCHEMA.CHARACTER_DATA
         *          CONSTRAINT ROLE_AUTHORIZATION_DESCRIPTORS_IS_GRANTABLE_CHECK
         *              CHECK ( IS_GRANTABLE IN
         *                  ( 'YES', 'NO' ) ),
         *          CONSTRAINT ROLE_AUTHORIZATION_DESCRIPTORS_PRIMARY_KEY
         *              PRIMARY KEY ( ROLE_NAME, GRANTEE ),
         *          CONSTRAINT ROLE_AUTHORIZATION_DESCRIPTORS_CHECK_ROLE_NAME
         *              CHECK ( ROLE_NAME IN
         *                  ( SELECT AUTHORIZATION_NAME
         *                      FROM AUTHORIZATIONS
         *                     WHERE AUTHORIZATION_TYPE = 'ROLE' ) ),
         *          CONSTRAINT ROLE_AUTHORIZATION_DESCRIPTORS_FOREIGN_KEY_AUTHORIZATIONS_GRANTOR
         *              FOREIGN KEY ( GRANTOR )
         *                  REFERENCES AUTHORIZATIONS,
         *          CONSTRAINT ROLE_AUTHORIZATION_DESCRIPTORS_FOREIGN_KEY_AUTHORIZATIONS_GRANTEE
         *              FOREIGN KEY ( GRANTEE )
         *                  REFERENCES AUTHORIZATIONS
         *      )
         * </pre>
         *
         * <b>Description</b><p>
         *
         * <ol>
         *      <li>The value of ROLE_NAME is the &lt;role name&gt; of some
         *          &lt;role granted&gt; by the &lt;grant role statement&gt; or
         *          the &lt;role name&gt; of a &lt;role definition&gt;. <p>
         *
         *      <li>The value of GRANTEE is an &lt;authorization identifier&gt;,
         *          possibly PUBLIC, or &lt;role name&gt; specified as a
         *          &lt;grantee&gt; contained in a &lt;grant role statement&gt;,
         *          or the &lt;authorization identifier&gt; of the current
         *          SQLsession when the &lt;role definition&gt; is executed. <p>
         *
         *      <li>The value of GRANTOR is the &lt;authorization identifier&gt;
         *          of the user or role who granted the role identified by
         *          ROLE_NAME to the user or role identified by the value of
         *          GRANTEE. <p>
         *
         *      <li>The values of IS_GRANTABLE have the following meanings:<p>
         *
         *      <table border cellpadding="3">
         *          <tr>
         *              <td nowrap>YES</td>
         *              <td nowrap>The described role is grantable.</td>
         *          <tr>
         *          <tr>
         *              <td nowrap>NO</td>
         *              <td nowrap>The described role is not grantable.</td>
         *          <tr>
         *      </table> <p>
         * </ol>
         *
         * @return Table
         */
        Table ROLE_AUTHORIZATION_DESCRIPTORS()
        {

            Table t = sysTables[ID_ROLE_AUTHORIZATION_DESCRIPTORS];

            if (t == null)
            {
                t = createBlankTable(
                    sysTableHsqlNames[ID_ROLE_AUTHORIZATION_DESCRIPTORS]);

                addColumn(t, "ROLE_NAME", SQL_IDENTIFIER);    // not null
                addColumn(t, "GRANTEE", SQL_IDENTIFIER);      // not null
                addColumn(t, "GRANTOR", SQL_IDENTIFIER);      // not null
                addColumn(t, "IS_GRANTABLE", YES_OR_NO);      // not null

                // true PK
                QNameManager.QName name = QNameManager.newInfoSchemaObjectName(
                    sysTableHsqlNames[ID_ROLE_AUTHORIZATION_DESCRIPTORS].name, false,
                    SchemaObjectTypes.INDEX);

                t.createPrimaryKey(name, new int[] {
                0, 1
            }, true);

                return t;
            }

            PersistentStore store = database.persistentStoreCollection.getStore(t);

            // Intermediate holders
            String grantorName = SqlInvariants.SYSTEM_AUTHORIZATION_NAME;
            Iterator grantees;
            Grantee granteeObject;
            String granteeName;
            Iterator roles;
            //String roleName;
            String isGrantable;
            Object[] row;

            // Column number mappings
            int role_name = 0;
            int grantee = 1;
            int grantor = 2;
            int is_grantable = 3;

            // Initialization
            grantees = session.getGrantee().visibleGrantees().iterator();

            //
            while (grantees.hasNext())
            {
                granteeObject = (Grantee)grantees.next();
                granteeName = granteeObject.getNameString();
                roles = granteeObject.getDirectRoles().iterator();
                isGrantable = granteeObject.isAdmin() ? Tokens.T_YES
                                                        : Tokens.T_NO; ;

                while (roles.hasNext())
                {
                    Grantee role = (Grantee)roles.next();

                    row = t.getEmptyRowData();
                    row[role_name] = role.getNameString();
                    row[grantee] = granteeName;
                    row[grantor] = grantorName;
                    row[is_grantable] = isGrantable;

                    t.insertSys(store, row);
                }
            }

            return t;
        }
    }
}
